blob: 69f2d07583d397cc7b4526343fbfa93a0bf3d717 [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"] = {}
Alexis Romeroef16c402022-03-11 15:29:18 +0100868 if db_nsr.get("affinity-or-anti-affinity-group"):
869 target["affinity-or-anti-affinity-group"] = deepcopy(db_nsr["affinity-or-anti-affinity-group"])
870 for affinity_or_anti_affinity_group in target["affinity-or-anti-affinity-group"]:
871 affinity_or_anti_affinity_group["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000872
tierno2357f4e2020-10-19 16:38:59 +0000873 if db_nslcmop.get("lcmOperationType") != "instantiate":
874 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100875 db_nslcmop_instantiate = self.db.get_list(
876 "nslcmops",
877 {
878 "nsInstanceId": db_nslcmop["nsInstanceId"],
879 "lcmOperationType": "instantiate",
880 },
881 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000882 ns_params = db_nslcmop_instantiate.get("operationParams")
883 else:
884 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300885 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
886 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000887
888 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000889 for vld_index, vld in enumerate(db_nsr.get("vld")):
890 target_vim = "vim:{}".format(ns_params["vimAccountId"])
891 target_vld = {
892 "id": vld["id"],
893 "name": vld["name"],
894 "mgmt-network": vld.get("mgmt-network", False),
895 "type": vld.get("type"),
896 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300897 target_vim: {
898 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100899 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300900 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100901 },
tierno2357f4e2020-10-19 16:38:59 +0000902 }
903 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000904 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000905 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +0000906 sdnc_id = db_vim["config"].get("sdn-controller")
907 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +0000908 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
909 target_sdn = "sdn:{}".format(sdnc_id)
910 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100911 "sdn": True,
912 "target_vim": target_vim,
913 "vlds": [sdn_vld],
914 "type": vld.get("type"),
915 }
tierno2357f4e2020-10-19 16:38:59 +0000916
bravof922c4172020-11-24 21:21:43 -0300917 nsd_vnf_profiles = get_vnf_profiles(nsd)
918 for nsd_vnf_profile in nsd_vnf_profiles:
919 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
920 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100921 cp2target[
922 "member_vnf:{}.{}".format(
923 cp["constituent-cpd-id"][0][
924 "constituent-base-element-id"
925 ],
926 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
927 )
928 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000929
930 # check at nsd descriptor, if there is an ip-profile
931 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000932 nsd_vlp = find_in_list(
933 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100934 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
935 == vld["id"],
936 )
937 if (
938 nsd_vlp
939 and nsd_vlp.get("virtual-link-protocol-data")
940 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
941 ):
942 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
943 "l3-protocol-data"
944 ]
lloretgalleg19008482021-04-19 11:40:18 +0000945 ip_profile_dest_data = {}
946 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100947 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
948 "ip-version"
949 ]
lloretgalleg19008482021-04-19 11:40:18 +0000950 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100951 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
952 "cidr"
953 ]
lloretgalleg19008482021-04-19 11:40:18 +0000954 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100955 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
956 "gateway-ip"
957 ]
lloretgalleg19008482021-04-19 11:40:18 +0000958 if "dhcp-enabled" in ip_profile_source_data:
959 ip_profile_dest_data["dhcp-params"] = {
960 "enabled": ip_profile_source_data["dhcp-enabled"]
961 }
962 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -0300963
tierno2357f4e2020-10-19 16:38:59 +0000964 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +0100965 vld_instantiation_params = find_in_list(
966 get_iterable(ns_params, "vld"),
967 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
968 )
tierno2357f4e2020-10-19 16:38:59 +0000969 if vld_instantiation_params:
970 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -0300971 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +0000972 target["ns"]["vld"].append(target_vld)
aticigc90db8e2022-03-11 21:14:22 +0300973 # Update the target ns_vld if vnf vim_account is overriden by instantiation params
974 update_ns_vld_target(target, ns_params)
bravof922c4172020-11-24 21:21:43 -0300975
tierno69f0d382020-05-07 13:08:09 +0000976 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +0100977 vnfd = find_in_list(
978 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
979 )
980 vnf_params = find_in_list(
981 get_iterable(ns_params, "vnf"),
982 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
983 )
tierno69f0d382020-05-07 13:08:09 +0000984 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +0000985 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +0000986 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +0000987 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +0100988 vnf_cp = find_in_list(
989 vnfd.get("int-virtual-link-desc", ()),
990 lambda cpd: cpd.get("id") == vld["id"],
991 )
tierno69f0d382020-05-07 13:08:09 +0000992 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +0100993 ns_cp = "member_vnf:{}.{}".format(
994 vnfr["member-vnf-index-ref"], vnf_cp["id"]
995 )
tierno69f0d382020-05-07 13:08:09 +0000996 if cp2target.get(ns_cp):
997 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -0300998
garciadeblas5697b8b2021-03-24 09:17:02 +0100999 vld["vim_info"] = {
1000 target_vim: {"vim_network_name": vld.get("vim-network-name")}
1001 }
tierno2357f4e2020-10-19 16:38:59 +00001002 # check if this network needs SDN assist
1003 target_sdn = None
1004 if vld.get("pci-interfaces"):
1005 db_vim = get_vim_account(vnfr["vim-account-id"])
1006 sdnc_id = db_vim["config"].get("sdn-controller")
1007 if sdnc_id:
1008 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
1009 target_sdn = "sdn:{}".format(sdnc_id)
1010 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001011 "sdn": True,
1012 "target_vim": target_vim,
1013 "vlds": [sdn_vld],
1014 "type": vld.get("type"),
1015 }
tierno69f0d382020-05-07 13:08:09 +00001016
tierno2357f4e2020-10-19 16:38:59 +00001017 # check at vnfd descriptor, if there is an ip-profile
1018 vld_params = {}
bravof922c4172020-11-24 21:21:43 -03001019 vnfd_vlp = find_in_list(
1020 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +01001021 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -03001022 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001023 if (
1024 vnfd_vlp
1025 and vnfd_vlp.get("virtual-link-protocol-data")
1026 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
1027 ):
1028 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
1029 "l3-protocol-data"
1030 ]
bravof922c4172020-11-24 21:21:43 -03001031 ip_profile_dest_data = {}
1032 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001033 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
1034 "ip-version"
1035 ]
bravof922c4172020-11-24 21:21:43 -03001036 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001037 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
1038 "cidr"
1039 ]
bravof922c4172020-11-24 21:21:43 -03001040 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +01001041 ip_profile_dest_data[
1042 "gateway-address"
1043 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -03001044 if "dhcp-enabled" in ip_profile_source_data:
1045 ip_profile_dest_data["dhcp-params"] = {
1046 "enabled": ip_profile_source_data["dhcp-enabled"]
1047 }
1048
1049 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +00001050 # update vld_params with instantiation params
1051 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01001052 vld_instantiation_params = find_in_list(
1053 get_iterable(vnf_params, "internal-vld"),
1054 lambda i_vld: i_vld["name"] == vld["id"],
1055 )
tierno2357f4e2020-10-19 16:38:59 +00001056 if vld_instantiation_params:
1057 vld_params.update(vld_instantiation_params)
1058 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
1059
1060 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001061 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001062 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1063 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001064 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001065
bravof922c4172020-11-24 21:21:43 -03001066 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1067
1068 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001069 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1070 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001071 if (
1072 vdu_configuration
1073 and vdu_configuration.get("config-access")
1074 and vdu_configuration.get("config-access").get("ssh-access")
1075 ):
bravof922c4172020-11-24 21:21:43 -03001076 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001077 vdur["ssh-access-required"] = vdu_configuration[
1078 "config-access"
1079 ]["ssh-access"]["required"]
1080 elif (
1081 vnf_configuration
1082 and vnf_configuration.get("config-access")
1083 and vnf_configuration.get("config-access").get("ssh-access")
1084 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1085 ):
bravof922c4172020-11-24 21:21:43 -03001086 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001087 vdur["ssh-access-required"] = vnf_configuration[
1088 "config-access"
1089 ]["ssh-access"]["required"]
1090 elif ssh_keys_instantiation and find_in_list(
1091 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1092 ):
bravof922c4172020-11-24 21:21:43 -03001093 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001094
bravof922c4172020-11-24 21:21:43 -03001095 self.logger.debug("NS > vdur > {}".format(vdur))
1096
1097 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001098 # cloud-init
1099 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001100 vdur["cloud-init"] = "{}:file:{}".format(
1101 vnfd["_id"], vdud.get("cloud-init-file")
1102 )
tierno2357f4e2020-10-19 16:38:59 +00001103 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1104 if vdur["cloud-init"] not in target["cloud_init_content"]:
1105 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001106 cloud_init_file = "{}/{}/cloud_init/{}".format(
1107 base_folder["folder"],
1108 base_folder["pkg-dir"],
1109 vdud.get("cloud-init-file"),
1110 )
tierno2357f4e2020-10-19 16:38:59 +00001111 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001112 target["cloud_init_content"][
1113 vdur["cloud-init"]
1114 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001115 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001116 vdur["cloud-init"] = "{}:vdu:{}".format(
1117 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1118 )
tierno2357f4e2020-10-19 16:38:59 +00001119 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001120 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1121 "cloud-init"
1122 ]
tierno2357f4e2020-10-19 16:38:59 +00001123 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001124 deploy_params_vdu = self._format_additional_params(
1125 vdur.get("additionalParams") or {}
1126 )
1127 deploy_params_vdu["OSM"] = get_osm_params(
1128 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1129 )
tierno2357f4e2020-10-19 16:38:59 +00001130 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001131
1132 # flavor
1133 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001134 if target_vim not in ns_flavor["vim_info"]:
1135 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001136
1137 # deal with images
1138 # in case alternative images are provided we must check if they should be applied
1139 # for the vim_type, modify the vim_type taking into account
1140 ns_image_id = int(vdur["ns-image-id"])
1141 if vdur.get("alt-image-ids"):
1142 db_vim = get_vim_account(vnfr["vim-account-id"])
1143 vim_type = db_vim["vim_type"]
1144 for alt_image_id in vdur.get("alt-image-ids"):
1145 ns_alt_image = target["image"][int(alt_image_id)]
1146 if vim_type == ns_alt_image.get("vim-type"):
1147 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001148 self.logger.debug(
1149 "use alternative image id: {}".format(alt_image_id)
1150 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001151 ns_image_id = alt_image_id
1152 vdur["ns-image-id"] = ns_image_id
1153 break
1154 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001155 if target_vim not in ns_image["vim_info"]:
1156 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001157
Alexis Romeroef16c402022-03-11 15:29:18 +01001158 # Affinity groups
1159 if vdur.get("affinity-or-anti-affinity-group-id"):
1160 for ags_id in vdur["affinity-or-anti-affinity-group-id"]:
1161 ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)]
1162 if target_vim not in ns_ags["vim_info"]:
1163 ns_ags["vim_info"][target_vim] = {}
1164
tierno2357f4e2020-10-19 16:38:59 +00001165 vdur["vim_info"] = {target_vim: {}}
1166 # instantiation parameters
1167 # if vnf_params:
1168 # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] ==
1169 # vdud["id"]), None)
1170 vdur_list.append(vdur)
1171 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001172 target["vnf"].append(target_vnf)
1173
1174 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001175 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001176 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001177 await self._wait_ng_ro(
1178 nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage
1179 )
tierno69f0d382020-05-07 13:08:09 +00001180
1181 # Updating NSR
1182 db_nsr_update = {
1183 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001184 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001185 }
1186 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1187 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1188 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001189 self.logger.debug(
1190 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1191 )
tierno69f0d382020-05-07 13:08:09 +00001192 return
1193
garciadeblas5697b8b2021-03-24 09:17:02 +01001194 async def _wait_ng_ro(
1195 self,
1196 nsr_id,
1197 action_id,
1198 nslcmop_id=None,
1199 start_time=None,
1200 timeout=600,
1201 stage=None,
1202 ):
tierno69f0d382020-05-07 13:08:09 +00001203 detailed_status_old = None
1204 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001205 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001206 while time() <= start_time + timeout:
1207 desc_status = await self.RO.status(nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001208 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001209 if desc_status["status"] == "FAILED":
1210 raise NgRoException(desc_status["details"])
1211 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001212 if stage:
1213 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001214 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001215 if stage:
1216 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001217 break
1218 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001219 assert False, "ROclient.check_ns_status returns unknown {}".format(
1220 desc_status["status"]
1221 )
tierno2357f4e2020-10-19 16:38:59 +00001222 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001223 detailed_status_old = stage[2]
1224 db_nsr_update["detailed-status"] = " ".join(stage)
1225 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1226 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001227 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001228 else: # timeout_ns_deploy
1229 raise NgRoException("Timeout waiting ns to deploy")
1230
garciadeblas5697b8b2021-03-24 09:17:02 +01001231 async def _terminate_ng_ro(
1232 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1233 ):
tierno69f0d382020-05-07 13:08:09 +00001234 db_nsr_update = {}
1235 failed_detail = []
1236 action_id = None
1237 start_deploy = time()
1238 try:
1239 target = {
1240 "ns": {"vld": []},
1241 "vnf": [],
1242 "image": [],
1243 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001244 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001245 }
1246 desc = await self.RO.deploy(nsr_id, target)
1247 action_id = desc["action_id"]
1248 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1249 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001250 self.logger.debug(
1251 logging_text
1252 + "ns terminate action at RO. action_id={}".format(action_id)
1253 )
tierno69f0d382020-05-07 13:08:09 +00001254
1255 # wait until done
1256 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001257 await self._wait_ng_ro(
1258 nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage
1259 )
tierno69f0d382020-05-07 13:08:09 +00001260
1261 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1262 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1263 # delete all nsr
1264 await self.RO.delete(nsr_id)
1265 except Exception as e:
1266 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1267 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1268 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1269 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001270 self.logger.debug(
1271 logging_text + "RO_action_id={} already deleted".format(action_id)
1272 )
tierno69f0d382020-05-07 13:08:09 +00001273 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1274 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001275 self.logger.debug(
1276 logging_text
1277 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1278 )
tierno69f0d382020-05-07 13:08:09 +00001279 else:
1280 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001281 self.logger.error(
1282 logging_text
1283 + "RO_action_id={} delete error: {}".format(action_id, e)
1284 )
tierno69f0d382020-05-07 13:08:09 +00001285
1286 if failed_detail:
1287 stage[2] = "Error deleting from VIM"
1288 else:
1289 stage[2] = "Deleted from VIM"
1290 db_nsr_update["detailed-status"] = " ".join(stage)
1291 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1292 self._write_op_status(nslcmop_id, stage)
1293
1294 if failed_detail:
1295 raise LcmException("; ".join(failed_detail))
1296 return
1297
garciadeblas5697b8b2021-03-24 09:17:02 +01001298 async def instantiate_RO(
1299 self,
1300 logging_text,
1301 nsr_id,
1302 nsd,
1303 db_nsr,
1304 db_nslcmop,
1305 db_vnfrs,
1306 db_vnfds,
1307 n2vc_key_list,
1308 stage,
1309 ):
tiernoe95ed362020-04-23 08:24:57 +00001310 """
1311 Instantiate at RO
1312 :param logging_text: preffix text to use at logging
1313 :param nsr_id: nsr identity
1314 :param nsd: database content of ns descriptor
1315 :param db_nsr: database content of ns record
1316 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1317 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001318 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001319 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1320 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1321 :return: None or exception
1322 """
tiernoe876f672020-02-13 14:34:48 +00001323 try:
tiernoe876f672020-02-13 14:34:48 +00001324 start_deploy = time()
1325 ns_params = db_nslcmop.get("operationParams")
1326 if ns_params and ns_params.get("timeout_ns_deploy"):
1327 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1328 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001329 timeout_ns_deploy = self.timeout.get(
1330 "ns_deploy", self.timeout_ns_deploy
1331 )
quilesj7e13aeb2019-10-08 13:34:55 +02001332
tiernoe876f672020-02-13 14:34:48 +00001333 # Check for and optionally request placement optimization. Database will be updated if placement activated
1334 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001335 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1336 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1337 for vnfr in db_vnfrs.values():
1338 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1339 break
1340 else:
1341 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001342
garciadeblas5697b8b2021-03-24 09:17:02 +01001343 return await self._instantiate_ng_ro(
1344 logging_text,
1345 nsr_id,
1346 nsd,
1347 db_nsr,
1348 db_nslcmop,
1349 db_vnfrs,
1350 db_vnfds,
1351 n2vc_key_list,
1352 stage,
1353 start_deploy,
1354 timeout_ns_deploy,
1355 )
tierno2357f4e2020-10-19 16:38:59 +00001356 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001357 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001358 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001359 self.logger.error(
1360 "Error deploying at VIM {}".format(e),
1361 exc_info=not isinstance(
1362 e,
1363 (
1364 ROclient.ROClientException,
1365 LcmException,
1366 DbException,
1367 NgRoException,
1368 ),
1369 ),
1370 )
tiernoe876f672020-02-13 14:34:48 +00001371 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001372
tierno7ecbc342020-09-21 14:05:39 +00001373 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1374 """
1375 Wait for kdu to be up, get ip address
1376 :param logging_text: prefix use for logging
1377 :param nsr_id:
1378 :param vnfr_id:
1379 :param kdu_name:
1380 :return: IP address
1381 """
1382
1383 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1384 nb_tries = 0
1385
1386 while nb_tries < 360:
1387 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001388 kdur = next(
1389 (
1390 x
1391 for x in get_iterable(db_vnfr, "kdur")
1392 if x.get("kdu-name") == kdu_name
1393 ),
1394 None,
1395 )
tierno7ecbc342020-09-21 14:05:39 +00001396 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001397 raise LcmException(
1398 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1399 )
tierno7ecbc342020-09-21 14:05:39 +00001400 if kdur.get("status"):
1401 if kdur["status"] in ("READY", "ENABLED"):
1402 return kdur.get("ip-address")
1403 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001404 raise LcmException(
1405 "target KDU={} is in error state".format(kdu_name)
1406 )
tierno7ecbc342020-09-21 14:05:39 +00001407
1408 await asyncio.sleep(10, loop=self.loop)
1409 nb_tries += 1
1410 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1411
garciadeblas5697b8b2021-03-24 09:17:02 +01001412 async def wait_vm_up_insert_key_ro(
1413 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1414 ):
tiernoa5088192019-11-26 16:12:53 +00001415 """
1416 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1417 :param logging_text: prefix use for logging
1418 :param nsr_id:
1419 :param vnfr_id:
1420 :param vdu_id:
1421 :param vdu_index:
1422 :param pub_key: public ssh key to inject, None to skip
1423 :param user: user to apply the public ssh key
1424 :return: IP address
1425 """
quilesj7e13aeb2019-10-08 13:34:55 +02001426
tierno2357f4e2020-10-19 16:38:59 +00001427 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001428 ro_nsr_id = None
1429 ip_address = None
1430 nb_tries = 0
1431 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001432 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001433
tiernod8323042019-08-09 11:32:23 +00001434 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001435
quilesj3149f262019-12-03 10:58:10 +00001436 ro_retries += 1
1437 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001438 raise LcmException(
1439 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1440 )
quilesj3149f262019-12-03 10:58:10 +00001441
tiernod8323042019-08-09 11:32:23 +00001442 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001443
1444 # get ip address
tiernod8323042019-08-09 11:32:23 +00001445 if not target_vdu_id:
1446 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001447
1448 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001449 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001450 raise LcmException(
1451 "Cannot inject ssh-key because target VNF is in error state"
1452 )
tiernod8323042019-08-09 11:32:23 +00001453 ip_address = db_vnfr.get("ip-address")
1454 if not ip_address:
1455 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001456 vdur = next(
1457 (
1458 x
1459 for x in get_iterable(db_vnfr, "vdur")
1460 if x.get("ip-address") == ip_address
1461 ),
1462 None,
1463 )
quilesj3149f262019-12-03 10:58:10 +00001464 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001465 vdur = next(
1466 (
1467 x
1468 for x in get_iterable(db_vnfr, "vdur")
1469 if x.get("vdu-id-ref") == vdu_id
1470 and x.get("count-index") == vdu_index
1471 ),
1472 None,
1473 )
quilesj3149f262019-12-03 10:58:10 +00001474
garciadeblas5697b8b2021-03-24 09:17:02 +01001475 if (
1476 not vdur and len(db_vnfr.get("vdur", ())) == 1
1477 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001478 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001479 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001480 raise LcmException(
1481 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1482 vnfr_id, vdu_id, vdu_index
1483 )
1484 )
tierno2357f4e2020-10-19 16:38:59 +00001485 # New generation RO stores information at "vim_info"
1486 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001487 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001488 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001489 target_vim = next(
1490 t for t in vdur["vim_info"]
1491 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001492 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001493 if (
1494 vdur.get("pdu-type")
1495 or vdur.get("status") == "ACTIVE"
1496 or ng_ro_status == "ACTIVE"
1497 ):
quilesj3149f262019-12-03 10:58:10 +00001498 ip_address = vdur.get("ip-address")
1499 if not ip_address:
1500 continue
1501 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001502 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001503 raise LcmException(
1504 "Cannot inject ssh-key because target VM is in error state"
1505 )
quilesj3149f262019-12-03 10:58:10 +00001506
tiernod8323042019-08-09 11:32:23 +00001507 if not target_vdu_id:
1508 continue
tiernod8323042019-08-09 11:32:23 +00001509
quilesj7e13aeb2019-10-08 13:34:55 +02001510 # inject public key into machine
1511 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001512 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001513 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001514 if vdur.get("pdu-type"):
1515 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1516 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001517 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001518 ro_vm_id = "{}-{}".format(
1519 db_vnfr["member-vnf-index-ref"], target_vdu_id
1520 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001521 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001522 target = {
1523 "action": {
1524 "action": "inject_ssh_key",
1525 "key": pub_key,
1526 "user": user,
1527 },
1528 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1529 }
tierno2357f4e2020-10-19 16:38:59 +00001530 desc = await self.RO.deploy(nsr_id, target)
1531 action_id = desc["action_id"]
1532 await self._wait_ng_ro(nsr_id, action_id, timeout=600)
1533 break
tierno69f0d382020-05-07 13:08:09 +00001534 else:
tierno2357f4e2020-10-19 16:38:59 +00001535 # wait until NS is deployed at RO
1536 if not ro_nsr_id:
1537 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001538 ro_nsr_id = deep_get(
1539 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1540 )
tierno2357f4e2020-10-19 16:38:59 +00001541 if not ro_nsr_id:
1542 continue
tierno69f0d382020-05-07 13:08:09 +00001543 result_dict = await self.RO.create_action(
1544 item="ns",
1545 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001546 descriptor={
1547 "add_public_key": pub_key,
1548 "vms": [ro_vm_id],
1549 "user": user,
1550 },
tierno69f0d382020-05-07 13:08:09 +00001551 )
1552 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1553 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001554 raise LcmException(
1555 "Unknown response from RO when injecting key"
1556 )
tierno69f0d382020-05-07 13:08:09 +00001557 for result in result_dict.values():
1558 if result.get("vim_result") == 200:
1559 break
1560 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001561 raise ROclient.ROClientException(
1562 "error injecting key: {}".format(
1563 result.get("description")
1564 )
1565 )
tierno69f0d382020-05-07 13:08:09 +00001566 break
1567 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001568 raise LcmException(
1569 "Reaching max tries injecting key. Error: {}".format(e)
1570 )
quilesj7e13aeb2019-10-08 13:34:55 +02001571 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001572 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001573 self.logger.debug(
1574 logging_text
1575 + "error injecting key: {}. Retrying until {} seconds".format(
1576 e, 20 * 10
1577 )
1578 )
quilesj7e13aeb2019-10-08 13:34:55 +02001579 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001580 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001581 raise LcmException(
1582 "Reaching max tries injecting key. Error: {}".format(e)
1583 )
quilesj7e13aeb2019-10-08 13:34:55 +02001584 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001585 break
1586
1587 return ip_address
1588
tierno5ee02052019-12-05 19:55:02 +00001589 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1590 """
1591 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1592 """
1593 my_vca = vca_deployed_list[vca_index]
1594 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001595 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001596 return
1597 timeout = 300
1598 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001599 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1600 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1601 configuration_status_list = db_nsr["configurationStatus"]
1602 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001603 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001604 # myself
tierno5ee02052019-12-05 19:55:02 +00001605 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001606 if not my_vca.get("member-vnf-index") or (
1607 vca_deployed.get("member-vnf-index")
1608 == my_vca.get("member-vnf-index")
1609 ):
quilesj3655ae02019-12-12 16:08:35 +00001610 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001611 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001612 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001613 elif internal_status == "BROKEN":
1614 raise LcmException(
1615 "Configuration aborted because dependent charm/s has failed"
1616 )
quilesj3655ae02019-12-12 16:08:35 +00001617 else:
1618 break
tierno5ee02052019-12-05 19:55:02 +00001619 else:
quilesj3655ae02019-12-12 16:08:35 +00001620 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001621 return
1622 await asyncio.sleep(10)
1623 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001624
1625 raise LcmException("Configuration aborted because dependent charm/s timeout")
1626
David Garciac1fe90a2021-03-31 19:12:02 +02001627 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia0b2b1882021-10-21 17:03:48 +02001628 vca_id = None
1629 if db_vnfr:
1630 vca_id = deep_get(db_vnfr, ("vca-id",))
1631 elif db_nsr:
1632 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1633 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1634 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001635
garciadeblas5697b8b2021-03-24 09:17:02 +01001636 async def instantiate_N2VC(
1637 self,
1638 logging_text,
1639 vca_index,
1640 nsi_id,
1641 db_nsr,
1642 db_vnfr,
1643 vdu_id,
1644 kdu_name,
1645 vdu_index,
1646 config_descriptor,
1647 deploy_params,
1648 base_folder,
1649 nslcmop_id,
1650 stage,
1651 vca_type,
1652 vca_name,
1653 ee_config_descriptor,
1654 ):
tiernod8323042019-08-09 11:32:23 +00001655 nsr_id = db_nsr["_id"]
1656 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001657 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001658 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001659 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001660 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001661 "collection": "nsrs",
1662 "filter": {"_id": nsr_id},
1663 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001664 }
tiernod8323042019-08-09 11:32:23 +00001665 step = ""
1666 try:
quilesj3655ae02019-12-12 16:08:35 +00001667
garciadeblas5697b8b2021-03-24 09:17:02 +01001668 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001669 element_under_configuration = nsr_id
1670
tiernod8323042019-08-09 11:32:23 +00001671 vnfr_id = None
1672 if db_vnfr:
1673 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001674 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001675
garciadeblas5697b8b2021-03-24 09:17:02 +01001676 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001677
aktas730569b2021-07-29 17:42:49 +03001678 if vca_type == "native_charm":
1679 index_number = 0
1680 else:
1681 index_number = vdu_index or 0
1682
tiernod8323042019-08-09 11:32:23 +00001683 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001684 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001685 element_under_configuration = vnfr_id
aktas730569b2021-07-29 17:42:49 +03001686 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001687 if vdu_id:
aktas730569b2021-07-29 17:42:49 +03001688 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001689 element_type = "VDU"
aktas730569b2021-07-29 17:42:49 +03001690 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001691 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001692 elif kdu_name:
aktas730569b2021-07-29 17:42:49 +03001693 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001694 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001695 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001696 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001697
1698 # Get artifact path
tierno588547c2020-07-01 15:30:20 +00001699 artifact_path = "{}/{}/{}/{}".format(
tiernod8323042019-08-09 11:32:23 +00001700 base_folder["folder"],
1701 base_folder["pkg-dir"],
garciadeblas5697b8b2021-03-24 09:17:02 +01001702 "charms"
1703 if vca_type in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
1704 else "helm-charts",
1705 vca_name,
tiernod8323042019-08-09 11:32:23 +00001706 )
bravof922c4172020-11-24 21:21:43 -03001707
1708 self.logger.debug("Artifact path > {}".format(artifact_path))
1709
tiernoa278b842020-07-08 15:33:55 +00001710 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001711 initial_config_primitive_list = config_descriptor.get(
1712 "initial-config-primitive"
1713 )
tiernoa278b842020-07-08 15:33:55 +00001714
garciadeblas5697b8b2021-03-24 09:17:02 +01001715 self.logger.debug(
1716 "Initial config primitive list > {}".format(
1717 initial_config_primitive_list
1718 )
1719 )
bravof922c4172020-11-24 21:21:43 -03001720
tiernoa278b842020-07-08 15:33:55 +00001721 # add config if not present for NS charm
1722 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001723 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001724 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1725 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1726 )
tiernod8323042019-08-09 11:32:23 +00001727
garciadeblas5697b8b2021-03-24 09:17:02 +01001728 self.logger.debug(
1729 "Initial config primitive list #2 > {}".format(
1730 initial_config_primitive_list
1731 )
1732 )
tierno588547c2020-07-01 15:30:20 +00001733 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001734 # find old ee_id if exists
1735 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001736
David Garciac1fe90a2021-03-31 19:12:02 +02001737 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001738 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001739 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001740
tierno588547c2020-07-01 15:30:20 +00001741 self._write_configuration_status(
1742 nsr_id=nsr_id,
1743 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001744 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001745 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001746 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001747 )
tiernod8323042019-08-09 11:32:23 +00001748
tierno588547c2020-07-01 15:30:20 +00001749 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001750 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001751
1752 ee_id = None
1753 credentials = None
1754 if vca_type == "k8s_proxy_charm":
1755 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001756 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001757 namespace=namespace,
1758 artifact_path=artifact_path,
1759 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001760 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001761 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001762 elif vca_type == "helm" or vca_type == "helm-v3":
1763 ee_id, credentials = await self.vca_map[
1764 vca_type
1765 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001766 namespace=namespace,
1767 reuse_ee_id=ee_id,
1768 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001769 config=osm_config,
1770 artifact_path=artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +01001771 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001772 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001773 else:
1774 ee_id, credentials = await self.vca_map[
1775 vca_type
1776 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001777 namespace=namespace,
1778 reuse_ee_id=ee_id,
1779 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001780 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001781 )
quilesj3655ae02019-12-12 16:08:35 +00001782
tierno588547c2020-07-01 15:30:20 +00001783 elif vca_type == "native_charm":
1784 step = "Waiting to VM being up and getting IP address"
1785 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001786 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1787 logging_text,
1788 nsr_id,
1789 vnfr_id,
1790 vdu_id,
1791 vdu_index,
1792 user=None,
1793 pub_key=None,
1794 )
tierno588547c2020-07-01 15:30:20 +00001795 credentials = {"hostname": rw_mgmt_ip}
1796 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001797 username = deep_get(
1798 config_descriptor, ("config-access", "ssh-access", "default-user")
1799 )
tierno588547c2020-07-01 15:30:20 +00001800 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1801 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001802 if not username and initial_config_primitive_list:
1803 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001804 for param in config_primitive.get("parameter", ()):
1805 if param["name"] == "ssh-username":
1806 username = param["value"]
1807 break
1808 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001809 raise LcmException(
1810 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1811 "'config-access.ssh-access.default-user'"
1812 )
tierno588547c2020-07-01 15:30:20 +00001813 credentials["username"] = username
1814 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001815
tierno588547c2020-07-01 15:30:20 +00001816 self._write_configuration_status(
1817 nsr_id=nsr_id,
1818 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001819 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001820 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001821 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001822 )
quilesj3655ae02019-12-12 16:08:35 +00001823
tierno588547c2020-07-01 15:30:20 +00001824 step = "register execution environment {}".format(credentials)
1825 self.logger.debug(logging_text + step)
1826 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001827 credentials=credentials,
1828 namespace=namespace,
1829 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001830 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001831 )
tierno3bedc9b2019-11-27 15:46:57 +00001832
tierno588547c2020-07-01 15:30:20 +00001833 # for compatibility with MON/POL modules, the need model and application name at database
1834 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001835 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001836 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1837 if len(ee_id_parts) >= 2:
1838 model_name = ee_id_parts[0]
1839 application_name = ee_id_parts[1]
1840 db_nsr_update[db_update_entry + "model"] = model_name
1841 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001842
1843 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001844 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001845
tiernoc231a872020-01-21 08:49:05 +00001846 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001847 nsr_id=nsr_id,
1848 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001849 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001850 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001851 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001852 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001853 )
1854
tierno3bedc9b2019-11-27 15:46:57 +00001855 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001856 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001857 config = None
tierno588547c2020-07-01 15:30:20 +00001858 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001859 config_primitive = next(
1860 (p for p in initial_config_primitive_list if p["name"] == "config"),
1861 None,
1862 )
tiernoa278b842020-07-08 15:33:55 +00001863 if config_primitive:
1864 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001865 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001866 )
tierno588547c2020-07-01 15:30:20 +00001867 num_units = 1
1868 if vca_type == "lxc_proxy_charm":
1869 if element_type == "NS":
1870 num_units = db_nsr.get("config-units") or 1
1871 elif element_type == "VNF":
1872 num_units = db_vnfr.get("config-units") or 1
1873 elif element_type == "VDU":
1874 for v in db_vnfr["vdur"]:
1875 if vdu_id == v["vdu-id-ref"]:
1876 num_units = v.get("config-units") or 1
1877 break
David Garciaaae391f2020-11-09 11:12:54 +01001878 if vca_type != "k8s_proxy_charm":
1879 await self.vca_map[vca_type].install_configuration_sw(
1880 ee_id=ee_id,
1881 artifact_path=artifact_path,
1882 db_dict=db_dict,
1883 config=config,
1884 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001885 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001886 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001887 )
quilesj7e13aeb2019-10-08 13:34:55 +02001888
quilesj63f90042020-01-17 09:53:55 +00001889 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001890 self.update_db_2(
1891 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1892 )
quilesj63f90042020-01-17 09:53:55 +00001893
1894 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01001895 await self._add_vca_relations(
1896 logging_text=logging_text,
1897 nsr_id=nsr_id,
1898 vca_index=vca_index,
1899 vca_id=vca_id,
1900 vca_type=vca_type,
1901 )
quilesj63f90042020-01-17 09:53:55 +00001902
quilesj7e13aeb2019-10-08 13:34:55 +02001903 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001904 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001905 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001906 pub_key = None
1907 user = None
tierno588547c2020-07-01 15:30:20 +00001908 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001909 if deep_get(
1910 config_descriptor, ("config-access", "ssh-access", "required")
1911 ):
tierno588547c2020-07-01 15:30:20 +00001912 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001913 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001914 user = deep_get(
1915 config_descriptor,
1916 ("config-access", "ssh-access", "default-user"),
1917 )
tierno3bedc9b2019-11-27 15:46:57 +00001918 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001919 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001920 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001921 )
quilesj7e13aeb2019-10-08 13:34:55 +02001922
garciadeblas5697b8b2021-03-24 09:17:02 +01001923 step = "Insert public key into VM user={} ssh_key={}".format(
1924 user, pub_key
1925 )
tierno3bedc9b2019-11-27 15:46:57 +00001926 else:
tierno588547c2020-07-01 15:30:20 +00001927 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001928 step = "Waiting to VM being up and getting IP address"
1929 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001930
tierno3bedc9b2019-11-27 15:46:57 +00001931 # n2vc_redesign STEP 5.1
1932 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001933 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001934 if kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01001935 rw_mgmt_ip = await self.wait_kdu_up(
1936 logging_text, nsr_id, vnfr_id, kdu_name
1937 )
tierno7ecbc342020-09-21 14:05:39 +00001938 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001939 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1940 logging_text,
1941 nsr_id,
1942 vnfr_id,
1943 vdu_id,
1944 vdu_index,
1945 user=user,
1946 pub_key=pub_key,
1947 )
tierno5ee02052019-12-05 19:55:02 +00001948 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001949 rw_mgmt_ip = None # This is for a NS configuration
tierno3bedc9b2019-11-27 15:46:57 +00001950
garciadeblas5697b8b2021-03-24 09:17:02 +01001951 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02001952
tiernoa5088192019-11-26 16:12:53 +00001953 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02001954 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00001955
1956 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01001957 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00001958
1959 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00001960 if initial_config_primitive_list:
1961 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00001962
1963 # stage, in function of element type: vdu, kdu, vnf or ns
1964 my_vca = vca_deployed_list[vca_index]
1965 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
1966 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01001967 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00001968 elif my_vca.get("member-vnf-index"):
1969 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01001970 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00001971 else:
1972 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01001973 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00001974
tiernoc231a872020-01-21 08:49:05 +00001975 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001976 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00001977 )
1978
garciadeblas5697b8b2021-03-24 09:17:02 +01001979 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00001980
tiernoe876f672020-02-13 14:34:48 +00001981 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00001982 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00001983 # adding information on the vca_deployed if it is a NS execution environment
1984 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001985 deploy_params["ns_config_info"] = json.dumps(
1986 self._get_ns_config_info(nsr_id)
1987 )
tiernod8323042019-08-09 11:32:23 +00001988 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01001989 primitive_params_ = self._map_primitive_params(
1990 initial_config_primitive, {}, deploy_params
1991 )
tierno3bedc9b2019-11-27 15:46:57 +00001992
garciadeblas5697b8b2021-03-24 09:17:02 +01001993 step = "execute primitive '{}' params '{}'".format(
1994 initial_config_primitive["name"], primitive_params_
1995 )
tiernod8323042019-08-09 11:32:23 +00001996 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00001997 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02001998 ee_id=ee_id,
1999 primitive_name=initial_config_primitive["name"],
2000 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02002001 db_dict=db_dict,
2002 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03002003 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02002004 )
tiernoe876f672020-02-13 14:34:48 +00002005 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
2006 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01002007 if config_descriptor.get("terminate-config-primitive"):
2008 self.update_db_2(
2009 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
2010 )
tiernoe876f672020-02-13 14:34:48 +00002011 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00002012
tiernod8323042019-08-09 11:32:23 +00002013 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02002014
tiernob996d942020-07-03 14:52:28 +00002015 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00002016 if vca_type == "helm" or vca_type == "helm-v3":
tiernob996d942020-07-03 14:52:28 +00002017 prometheus_jobs = await self.add_prometheus_metrics(
2018 ee_id=ee_id,
2019 artifact_path=artifact_path,
2020 ee_config_descriptor=ee_config_descriptor,
2021 vnfr_id=vnfr_id,
2022 nsr_id=nsr_id,
2023 target_ip=rw_mgmt_ip,
2024 )
2025 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01002026 self.update_db_2(
2027 "nsrs",
2028 nsr_id,
2029 {db_update_entry + "prometheus_jobs": prometheus_jobs},
2030 )
tiernob996d942020-07-03 14:52:28 +00002031
quilesj7e13aeb2019-10-08 13:34:55 +02002032 step = "instantiated at VCA"
2033 self.logger.debug(logging_text + step)
2034
tiernoc231a872020-01-21 08:49:05 +00002035 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002036 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00002037 )
2038
tiernod8323042019-08-09 11:32:23 +00002039 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00002040 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01002041 if not isinstance(
2042 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
2043 ):
2044 self.logger.error(
2045 "Exception while {} : {}".format(step, e), exc_info=True
2046 )
tiernoc231a872020-01-21 08:49:05 +00002047 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01002048 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00002049 )
tiernoe876f672020-02-13 14:34:48 +00002050 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00002051
garciadeblas5697b8b2021-03-24 09:17:02 +01002052 def _write_ns_status(
2053 self,
2054 nsr_id: str,
2055 ns_state: str,
2056 current_operation: str,
2057 current_operation_id: str,
2058 error_description: str = None,
2059 error_detail: str = None,
2060 other_update: dict = None,
2061 ):
tiernoe876f672020-02-13 14:34:48 +00002062 """
2063 Update db_nsr fields.
2064 :param nsr_id:
2065 :param ns_state:
2066 :param current_operation:
2067 :param current_operation_id:
2068 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002069 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002070 :param other_update: Other required changes at database if provided, will be cleared
2071 :return:
2072 """
quilesj4cda56b2019-12-05 10:02:20 +00002073 try:
tiernoe876f672020-02-13 14:34:48 +00002074 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002075 db_dict[
2076 "_admin.nslcmop"
2077 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002078 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002079 db_dict["_admin.operation-type"] = (
2080 current_operation if current_operation != "IDLE" else None
2081 )
quilesj4cda56b2019-12-05 10:02:20 +00002082 db_dict["currentOperation"] = current_operation
2083 db_dict["currentOperationID"] = current_operation_id
2084 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002085 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002086
2087 if ns_state:
2088 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002089 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002090 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002091 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002092
garciadeblas5697b8b2021-03-24 09:17:02 +01002093 def _write_op_status(
2094 self,
2095 op_id: str,
2096 stage: list = None,
2097 error_message: str = None,
2098 queuePosition: int = 0,
2099 operation_state: str = None,
2100 other_update: dict = None,
2101 ):
quilesj3655ae02019-12-12 16:08:35 +00002102 try:
tiernoe876f672020-02-13 14:34:48 +00002103 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002104 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002105 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002106 db_dict["stage"] = stage[0]
2107 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002108 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002109 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002110
2111 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002112 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002113 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002114 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002115 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002116 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002117 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002118 self.logger.warn(
2119 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2120 )
quilesj3655ae02019-12-12 16:08:35 +00002121
tierno51183952020-04-03 15:48:18 +00002122 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002123 try:
tierno51183952020-04-03 15:48:18 +00002124 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002125 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002126 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002127 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002128 db_nsr_update = {
2129 "configurationStatus.{}.status".format(index): status
2130 for index, v in enumerate(config_status)
2131 if v
2132 }
quilesj3655ae02019-12-12 16:08:35 +00002133 # update status
tierno51183952020-04-03 15:48:18 +00002134 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002135
tiernoe876f672020-02-13 14:34:48 +00002136 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002137 self.logger.warn(
2138 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2139 )
quilesj3655ae02019-12-12 16:08:35 +00002140
garciadeblas5697b8b2021-03-24 09:17:02 +01002141 def _write_configuration_status(
2142 self,
2143 nsr_id: str,
2144 vca_index: int,
2145 status: str = None,
2146 element_under_configuration: str = None,
2147 element_type: str = None,
2148 other_update: dict = None,
2149 ):
quilesj3655ae02019-12-12 16:08:35 +00002150
2151 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2152 # .format(vca_index, status))
2153
2154 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002155 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002156 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002157 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002158 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002159 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002160 db_dict[
2161 db_path + "elementUnderConfiguration"
2162 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002163 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002164 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002165 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002166 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002167 self.logger.warn(
2168 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2169 status, nsr_id, vca_index, e
2170 )
2171 )
quilesj4cda56b2019-12-05 10:02:20 +00002172
tierno38089af2020-04-16 07:56:58 +00002173 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2174 """
2175 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2176 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2177 Database is used because the result can be obtained from a different LCM worker in case of HA.
2178 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2179 :param db_nslcmop: database content of nslcmop
2180 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002181 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2182 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002183 """
tierno8790a3d2020-04-23 22:49:52 +00002184 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002185 nslcmop_id = db_nslcmop["_id"]
2186 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002187 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002188 self.logger.debug(
2189 logging_text + "Invoke and wait for placement optimization"
2190 )
2191 await self.msg.aiowrite(
2192 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2193 )
magnussonle9198bb2020-01-21 13:00:51 +01002194 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002195 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002196 pla_result = None
2197 while not pla_result and wait >= 0:
2198 await asyncio.sleep(db_poll_interval)
2199 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002200 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002201 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002202
2203 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002204 raise LcmException(
2205 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2206 )
magnussonle9198bb2020-01-21 13:00:51 +01002207
garciadeblas5697b8b2021-03-24 09:17:02 +01002208 for pla_vnf in pla_result["vnf"]:
2209 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2210 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002211 continue
tierno8790a3d2020-04-23 22:49:52 +00002212 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002213 self.db.set_one(
2214 "vnfrs",
2215 {"_id": vnfr["_id"]},
2216 {"vim-account-id": pla_vnf["vimAccountId"]},
2217 )
tierno38089af2020-04-16 07:56:58 +00002218 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002219 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002220 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002221
2222 def update_nsrs_with_pla_result(self, params):
2223 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002224 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2225 self.update_db_2(
2226 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2227 )
magnussonle9198bb2020-01-21 13:00:51 +01002228 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002229 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002230
tierno59d22d22018-09-25 18:10:19 +02002231 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002232 """
2233
2234 :param nsr_id: ns instance to deploy
2235 :param nslcmop_id: operation to run
2236 :return:
2237 """
kuused124bfe2019-06-18 12:09:24 +02002238
2239 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002240 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002241 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002242 self.logger.debug(
2243 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2244 )
kuused124bfe2019-06-18 12:09:24 +02002245 return
2246
tierno59d22d22018-09-25 18:10:19 +02002247 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2248 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002249
tierno59d22d22018-09-25 18:10:19 +02002250 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002251
2252 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002253 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002254
2255 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002256 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002257
2258 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002259 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002260 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002261 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002262
tierno59d22d22018-09-25 18:10:19 +02002263 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002264 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002265 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002266 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002267 exc = None
tiernoe876f672020-02-13 14:34:48 +00002268 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002269 stage = [
2270 "Stage 1/5: preparation of the environment.",
2271 "Waiting for previous operations to terminate.",
2272 "",
2273 ]
tiernoe876f672020-02-13 14:34:48 +00002274 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002275 try:
kuused124bfe2019-06-18 12:09:24 +02002276 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002277 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002278
quilesj7e13aeb2019-10-08 13:34:55 +02002279 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002280 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002281 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002282 db_nsr_update["detailed-status"] = "creating"
2283 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002284 self._write_ns_status(
2285 nsr_id=nsr_id,
2286 ns_state="BUILDING",
2287 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002288 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002289 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002290 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002291 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002292
quilesj7e13aeb2019-10-08 13:34:55 +02002293 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002294 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002295 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002296 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2297 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2298 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2299 )
tierno744303e2020-01-13 16:46:31 +00002300 ns_params = db_nslcmop.get("operationParams")
2301 if ns_params and ns_params.get("timeout_ns_deploy"):
2302 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2303 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002304 timeout_ns_deploy = self.timeout.get(
2305 "ns_deploy", self.timeout_ns_deploy
2306 )
quilesj7e13aeb2019-10-08 13:34:55 +02002307
2308 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002309 stage[1] = "Getting nsr={} from db.".format(nsr_id)
tierno59d22d22018-09-25 18:10:19 +02002310 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002311 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002312 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002313 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002314 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002315 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002316
quilesj7e13aeb2019-10-08 13:34:55 +02002317 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002318 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002319 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002320 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002321
quilesj7e13aeb2019-10-08 13:34:55 +02002322 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002323 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002324
2325 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002326 for vnfr in db_vnfrs_list:
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002327 if vnfr.get("kdur"):
2328 kdur_list = []
2329 for kdur in vnfr["kdur"]:
2330 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01002331 kdur["additionalParams"] = json.loads(
2332 kdur["additionalParams"]
2333 )
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002334 kdur_list.append(kdur)
2335 vnfr["kdur"] = kdur_list
2336
bravof922c4172020-11-24 21:21:43 -03002337 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2338 vnfd_id = vnfr["vnfd-id"]
2339 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002340 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002341
quilesj7e13aeb2019-10-08 13:34:55 +02002342 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002343 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002344 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002345 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2346 vnfd_id, vnfd_ref
2347 )
tiernoe876f672020-02-13 14:34:48 +00002348 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002349 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002350
quilesj7e13aeb2019-10-08 13:34:55 +02002351 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002352 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002353
2354 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002355 vca_deployed_list = None
2356 if db_nsr["_admin"].get("deployed"):
2357 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2358 if vca_deployed_list is None:
2359 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002360 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002361 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002362 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002363 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002364 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002365 elif isinstance(vca_deployed_list, dict):
2366 # maintain backward compatibility. Change a dict to list at database
2367 vca_deployed_list = list(vca_deployed_list.values())
2368 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002369 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002370
garciadeblas5697b8b2021-03-24 09:17:02 +01002371 if not isinstance(
2372 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2373 ):
tiernoa009e552019-01-30 16:45:44 +00002374 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2375 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002376
tiernobaa51102018-12-14 13:16:18 +00002377 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2378 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2379 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002380 self.db.set_list(
2381 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2382 )
quilesj3655ae02019-12-12 16:08:35 +00002383
2384 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002385 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2386 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002387
tiernob5203912020-08-11 11:20:13 +00002388 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002389 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002390 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002391 await self.deploy_kdus(
2392 logging_text=logging_text,
2393 nsr_id=nsr_id,
2394 nslcmop_id=nslcmop_id,
2395 db_vnfrs=db_vnfrs,
2396 db_vnfds=db_vnfds,
2397 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002398 )
tiernoe876f672020-02-13 14:34:48 +00002399
2400 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002401 # n2vc_redesign STEP 1 Get VCA public ssh-key
2402 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002403 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002404 n2vc_key_list = [n2vc_key]
2405 if self.vca_config.get("public_key"):
2406 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002407
tiernoe876f672020-02-13 14:34:48 +00002408 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002409 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002410 self.instantiate_RO(
2411 logging_text=logging_text,
2412 nsr_id=nsr_id,
2413 nsd=nsd,
2414 db_nsr=db_nsr,
2415 db_nslcmop=db_nslcmop,
2416 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002417 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002418 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002419 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002420 )
tiernod8323042019-08-09 11:32:23 +00002421 )
2422 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002423 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002424
tiernod8323042019-08-09 11:32:23 +00002425 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002426 stage[1] = "Deploying Execution Environments."
2427 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002428
tiernod8323042019-08-09 11:32:23 +00002429 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002430 for vnf_profile in get_vnf_profiles(nsd):
2431 vnfd_id = vnf_profile["vnfd-id"]
2432 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2433 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002434 db_vnfr = db_vnfrs[member_vnf_index]
2435 base_folder = vnfd["_admin"]["storage"]
2436 vdu_id = None
2437 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002438 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002439 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002440
tierno8a518872018-12-21 13:42:14 +00002441 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002442 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002443 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002444 deploy_params.update(
2445 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2446 )
tierno8a518872018-12-21 13:42:14 +00002447
bravofe5a31bc2021-02-17 19:09:12 -03002448 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002449 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002450 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002451 logging_text=logging_text
2452 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002453 db_nsr=db_nsr,
2454 db_vnfr=db_vnfr,
2455 nslcmop_id=nslcmop_id,
2456 nsr_id=nsr_id,
2457 nsi_id=nsi_id,
2458 vnfd_id=vnfd_id,
2459 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002460 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002461 member_vnf_index=member_vnf_index,
2462 vdu_index=vdu_index,
2463 vdu_name=vdu_name,
2464 deploy_params=deploy_params,
2465 descriptor_config=descriptor_config,
2466 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002467 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002468 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002469 )
tierno59d22d22018-09-25 18:10:19 +02002470
2471 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002472 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002473 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002474 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002475 vdur = find_in_list(
2476 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2477 )
bravof922c4172020-11-24 21:21:43 -03002478
tierno626e0152019-11-29 14:16:16 +00002479 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002480 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002481 else:
2482 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002483 deploy_params_vdu["OSM"] = get_osm_params(
2484 db_vnfr, vdu_id, vdu_count_index=0
2485 )
endika85d73a62021-06-21 18:55:07 +02002486 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002487
2488 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002489 self.logger.debug(
2490 "Descriptor config > {}".format(descriptor_config)
2491 )
tierno588547c2020-07-01 15:30:20 +00002492 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002493 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002494 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002495 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002496 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002497 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002498 logging_text=logging_text
2499 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2500 member_vnf_index, vdu_id, vdu_index
2501 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002502 db_nsr=db_nsr,
2503 db_vnfr=db_vnfr,
2504 nslcmop_id=nslcmop_id,
2505 nsr_id=nsr_id,
2506 nsi_id=nsi_id,
2507 vnfd_id=vnfd_id,
2508 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002509 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002510 member_vnf_index=member_vnf_index,
2511 vdu_index=vdu_index,
2512 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002513 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002514 descriptor_config=descriptor_config,
2515 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002516 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002517 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002518 )
bravof922c4172020-11-24 21:21:43 -03002519 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002520 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002521 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002522 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002523 vdu_id = None
2524 vdu_index = 0
2525 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002526 kdur = next(
2527 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2528 )
bravof922c4172020-11-24 21:21:43 -03002529 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002530 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01002531 deploy_params_kdu.update(
2532 parse_yaml_strings(kdur["additionalParams"].copy())
garciadeblas5697b8b2021-03-24 09:17:02 +01002533 )
tierno59d22d22018-09-25 18:10:19 +02002534
calvinosanch9f9c6f22019-11-04 13:37:39 +01002535 self._deploy_n2vc(
2536 logging_text=logging_text,
2537 db_nsr=db_nsr,
2538 db_vnfr=db_vnfr,
2539 nslcmop_id=nslcmop_id,
2540 nsr_id=nsr_id,
2541 nsi_id=nsi_id,
2542 vnfd_id=vnfd_id,
2543 vdu_id=vdu_id,
2544 kdu_name=kdu_name,
2545 member_vnf_index=member_vnf_index,
2546 vdu_index=vdu_index,
2547 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002548 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002549 descriptor_config=descriptor_config,
2550 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002551 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002552 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002553 )
tierno59d22d22018-09-25 18:10:19 +02002554
tierno1b633412019-02-25 16:48:23 +00002555 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002556 descriptor_config = nsd.get("ns-configuration")
2557 if descriptor_config and descriptor_config.get("juju"):
2558 vnfd_id = None
2559 db_vnfr = None
2560 member_vnf_index = None
2561 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002562 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002563 vdu_index = 0
2564 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002565
tiernod8323042019-08-09 11:32:23 +00002566 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002567 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002568 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002569 deploy_params.update(
2570 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2571 )
tiernod8323042019-08-09 11:32:23 +00002572 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002573 self._deploy_n2vc(
2574 logging_text=logging_text,
2575 db_nsr=db_nsr,
2576 db_vnfr=db_vnfr,
2577 nslcmop_id=nslcmop_id,
2578 nsr_id=nsr_id,
2579 nsi_id=nsi_id,
2580 vnfd_id=vnfd_id,
2581 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002582 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002583 member_vnf_index=member_vnf_index,
2584 vdu_index=vdu_index,
2585 vdu_name=vdu_name,
2586 deploy_params=deploy_params,
2587 descriptor_config=descriptor_config,
2588 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002589 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002590 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002591 )
tierno1b633412019-02-25 16:48:23 +00002592
tiernoe876f672020-02-13 14:34:48 +00002593 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002594
garciadeblas5697b8b2021-03-24 09:17:02 +01002595 except (
2596 ROclient.ROClientException,
2597 DbException,
2598 LcmException,
2599 N2VCException,
2600 ) as e:
2601 self.logger.error(
2602 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2603 )
tierno59d22d22018-09-25 18:10:19 +02002604 exc = e
2605 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002606 self.logger.error(
2607 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2608 )
tierno59d22d22018-09-25 18:10:19 +02002609 exc = "Operation was cancelled"
2610 except Exception as e:
2611 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002612 self.logger.critical(
2613 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2614 exc_info=True,
2615 )
tierno59d22d22018-09-25 18:10:19 +02002616 finally:
2617 if exc:
tiernoe876f672020-02-13 14:34:48 +00002618 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002619 try:
tiernoe876f672020-02-13 14:34:48 +00002620 # wait for pending tasks
2621 if tasks_dict_info:
2622 stage[1] = "Waiting for instantiate pending tasks."
2623 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002624 error_list += await self._wait_for_tasks(
2625 logging_text,
2626 tasks_dict_info,
2627 timeout_ns_deploy,
2628 stage,
2629 nslcmop_id,
2630 nsr_id=nsr_id,
2631 )
tiernoe876f672020-02-13 14:34:48 +00002632 stage[1] = stage[2] = ""
2633 except asyncio.CancelledError:
2634 error_list.append("Cancelled")
2635 # TODO cancel all tasks
2636 except Exception as exc:
2637 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002638
tiernoe876f672020-02-13 14:34:48 +00002639 # update operation-status
2640 db_nsr_update["operational-status"] = "running"
2641 # let's begin with VCA 'configured' status (later we can change it)
2642 db_nsr_update["config-status"] = "configured"
2643 for task, task_name in tasks_dict_info.items():
2644 if not task.done() or task.cancelled() or task.exception():
2645 if task_name.startswith(self.task_name_deploy_vca):
2646 # A N2VC task is pending
2647 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002648 else:
tiernoe876f672020-02-13 14:34:48 +00002649 # RO or KDU task is pending
2650 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002651
tiernoe876f672020-02-13 14:34:48 +00002652 # update status at database
2653 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002654 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002655 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002656 error_description_nslcmop = "{} Detail: {}".format(
2657 stage[0], error_detail
2658 )
2659 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2660 nslcmop_id, stage[0]
2661 )
quilesj3655ae02019-12-12 16:08:35 +00002662
garciadeblas5697b8b2021-03-24 09:17:02 +01002663 db_nsr_update["detailed-status"] = (
2664 error_description_nsr + " Detail: " + error_detail
2665 )
tiernoe876f672020-02-13 14:34:48 +00002666 db_nslcmop_update["detailed-status"] = error_detail
2667 nslcmop_operation_state = "FAILED"
2668 ns_state = "BROKEN"
2669 else:
tiernoa2143262020-03-27 16:20:40 +00002670 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002671 error_description_nsr = error_description_nslcmop = None
2672 ns_state = "READY"
2673 db_nsr_update["detailed-status"] = "Done"
2674 db_nslcmop_update["detailed-status"] = "Done"
2675 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002676
tiernoe876f672020-02-13 14:34:48 +00002677 if db_nsr:
2678 self._write_ns_status(
2679 nsr_id=nsr_id,
2680 ns_state=ns_state,
2681 current_operation="IDLE",
2682 current_operation_id=None,
2683 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002684 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002685 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002686 )
tiernoa17d4f42020-04-28 09:59:23 +00002687 self._write_op_status(
2688 op_id=nslcmop_id,
2689 stage="",
2690 error_message=error_description_nslcmop,
2691 operation_state=nslcmop_operation_state,
2692 other_update=db_nslcmop_update,
2693 )
quilesj3655ae02019-12-12 16:08:35 +00002694
tierno59d22d22018-09-25 18:10:19 +02002695 if nslcmop_operation_state:
2696 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002697 await self.msg.aiowrite(
2698 "ns",
2699 "instantiated",
2700 {
2701 "nsr_id": nsr_id,
2702 "nslcmop_id": nslcmop_id,
2703 "operationState": nslcmop_operation_state,
2704 },
2705 loop=self.loop,
2706 )
tierno59d22d22018-09-25 18:10:19 +02002707 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002708 self.logger.error(
2709 logging_text + "kafka_write notification Exception {}".format(e)
2710 )
tierno59d22d22018-09-25 18:10:19 +02002711
2712 self.logger.debug(logging_text + "Exit")
2713 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2714
David Garciac1fe90a2021-03-31 19:12:02 +02002715 async def _add_vca_relations(
2716 self,
2717 logging_text,
2718 nsr_id,
2719 vca_index: int,
2720 timeout: int = 3600,
2721 vca_type: str = None,
2722 vca_id: str = None,
2723 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00002724
2725 # steps:
2726 # 1. find all relations for this VCA
2727 # 2. wait for other peers related
2728 # 3. add relations
2729
2730 try:
tierno588547c2020-07-01 15:30:20 +00002731 vca_type = vca_type or "lxc_proxy_charm"
quilesj63f90042020-01-17 09:53:55 +00002732
2733 # STEP 1: find all relations for this VCA
2734
2735 # read nsr record
2736 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garcia171f3542020-05-21 16:41:07 +02002737 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
quilesj63f90042020-01-17 09:53:55 +00002738
2739 # this VCA data
garciadeblas5697b8b2021-03-24 09:17:02 +01002740 my_vca = deep_get(db_nsr, ("_admin", "deployed", "VCA"))[vca_index]
quilesj63f90042020-01-17 09:53:55 +00002741
2742 # read all ns-configuration relations
2743 ns_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002744 db_ns_relations = deep_get(nsd, ("ns-configuration", "relation"))
quilesj63f90042020-01-17 09:53:55 +00002745 if db_ns_relations:
2746 for r in db_ns_relations:
2747 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002748 if my_vca.get("member-vnf-index") in (
2749 r.get("entities")[0].get("id"),
2750 r.get("entities")[1].get("id"),
2751 ):
quilesj63f90042020-01-17 09:53:55 +00002752 ns_relations.append(r)
2753
2754 # read all vnf-configuration relations
2755 vnf_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002756 db_vnfd_list = db_nsr.get("vnfd-id")
quilesj63f90042020-01-17 09:53:55 +00002757 if db_vnfd_list:
2758 for vnfd in db_vnfd_list:
aktas45966a02021-05-04 19:32:45 +03002759 db_vnf_relations = None
quilesj63f90042020-01-17 09:53:55 +00002760 db_vnfd = self.db.get_one("vnfds", {"_id": vnfd})
aktas45966a02021-05-04 19:32:45 +03002761 db_vnf_configuration = get_configuration(db_vnfd, db_vnfd["id"])
2762 if db_vnf_configuration:
2763 db_vnf_relations = db_vnf_configuration.get("relation", [])
quilesj63f90042020-01-17 09:53:55 +00002764 if db_vnf_relations:
2765 for r in db_vnf_relations:
2766 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002767 if my_vca.get("vdu_id") in (
2768 r.get("entities")[0].get("id"),
2769 r.get("entities")[1].get("id"),
2770 ):
quilesj63f90042020-01-17 09:53:55 +00002771 vnf_relations.append(r)
2772
2773 # if no relations, terminate
2774 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002775 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00002776 return True
2777
garciadeblas5697b8b2021-03-24 09:17:02 +01002778 self.logger.debug(
2779 logging_text
2780 + " adding relations\n {}\n {}".format(
2781 ns_relations, vnf_relations
2782 )
2783 )
quilesj63f90042020-01-17 09:53:55 +00002784
2785 # add all relations
2786 start = time()
2787 while True:
2788 # check timeout
2789 now = time()
2790 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01002791 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00002792 return False
2793
2794 # reload nsr from database (we need to update record: _admin.deloyed.VCA)
2795 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
2796
2797 # for each defined NS relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002798 for r in ns_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002799 from_vca_ee_id = None
2800 to_vca_ee_id = None
2801 from_vca_endpoint = None
2802 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002803 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002804 for vca in vca_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01002805 if vca.get("member-vnf-index") == r.get("entities")[0].get(
2806 "id"
2807 ) and vca.get("config_sw_installed"):
2808 from_vca_ee_id = vca.get("ee_id")
2809 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2810 if vca.get("member-vnf-index") == r.get("entities")[1].get(
2811 "id"
2812 ) and vca.get("config_sw_installed"):
2813 to_vca_ee_id = vca.get("ee_id")
2814 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002815 if from_vca_ee_id and to_vca_ee_id:
2816 # add relation
tierno588547c2020-07-01 15:30:20 +00002817 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002818 ee_id_1=from_vca_ee_id,
2819 ee_id_2=to_vca_ee_id,
2820 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002821 endpoint_2=to_vca_endpoint,
2822 vca_id=vca_id,
2823 )
quilesj63f90042020-01-17 09:53:55 +00002824 # remove entry from relations list
2825 ns_relations.remove(r)
2826 else:
2827 # check failed peers
2828 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002829 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002830 if vca_status_list:
2831 for i in range(len(vca_list)):
2832 vca = vca_list[i]
2833 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002834 if vca.get("member-vnf-index") == r.get("entities")[
2835 0
2836 ].get("id"):
2837 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002838 # peer broken: remove relation from list
2839 ns_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002840 if vca.get("member-vnf-index") == r.get("entities")[
2841 1
2842 ].get("id"):
2843 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002844 # peer broken: remove relation from list
2845 ns_relations.remove(r)
2846 except Exception:
2847 # ignore
2848 pass
2849
2850 # for each defined VNF relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002851 for r in vnf_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002852 from_vca_ee_id = None
2853 to_vca_ee_id = None
2854 from_vca_endpoint = None
2855 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002856 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002857 for vca in vca_list:
David Garcia97be6832020-09-09 15:40:44 +02002858 key_to_check = "vdu_id"
2859 if vca.get("vdu_id") is None:
2860 key_to_check = "vnfd_id"
garciadeblas5697b8b2021-03-24 09:17:02 +01002861 if vca.get(key_to_check) == r.get("entities")[0].get(
2862 "id"
2863 ) and vca.get("config_sw_installed"):
2864 from_vca_ee_id = vca.get("ee_id")
2865 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2866 if vca.get(key_to_check) == r.get("entities")[1].get(
2867 "id"
2868 ) and vca.get("config_sw_installed"):
2869 to_vca_ee_id = vca.get("ee_id")
2870 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002871 if from_vca_ee_id and to_vca_ee_id:
2872 # add relation
tierno588547c2020-07-01 15:30:20 +00002873 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002874 ee_id_1=from_vca_ee_id,
2875 ee_id_2=to_vca_ee_id,
2876 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002877 endpoint_2=to_vca_endpoint,
2878 vca_id=vca_id,
2879 )
quilesj63f90042020-01-17 09:53:55 +00002880 # remove entry from relations list
2881 vnf_relations.remove(r)
2882 else:
2883 # check failed peers
2884 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002885 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002886 if vca_status_list:
2887 for i in range(len(vca_list)):
2888 vca = vca_list[i]
2889 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002890 if vca.get("vdu_id") == r.get("entities")[0].get(
2891 "id"
2892 ):
2893 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002894 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002895 vnf_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002896 if vca.get("vdu_id") == r.get("entities")[1].get(
2897 "id"
2898 ):
2899 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002900 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002901 vnf_relations.remove(r)
quilesj63f90042020-01-17 09:53:55 +00002902 except Exception:
2903 # ignore
2904 pass
2905
2906 # wait for next try
2907 await asyncio.sleep(5.0)
2908
2909 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002910 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00002911 break
2912
2913 return True
2914
2915 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002916 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00002917 return False
2918
garciadeblas5697b8b2021-03-24 09:17:02 +01002919 async def _install_kdu(
2920 self,
2921 nsr_id: str,
2922 nsr_db_path: str,
2923 vnfr_data: dict,
2924 kdu_index: int,
2925 kdud: dict,
2926 vnfd: dict,
2927 k8s_instance_info: dict,
2928 k8params: dict = None,
2929 timeout: int = 600,
2930 vca_id: str = None,
2931 ):
lloretgalleg7c121132020-07-08 07:53:22 +00002932
tiernob9018152020-04-16 14:18:24 +00002933 try:
lloretgalleg7c121132020-07-08 07:53:22 +00002934 k8sclustertype = k8s_instance_info["k8scluster-type"]
2935 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01002936 db_dict_install = {
2937 "collection": "nsrs",
2938 "filter": {"_id": nsr_id},
2939 "path": nsr_db_path,
2940 }
lloretgalleg7c121132020-07-08 07:53:22 +00002941
romeromonser4e71ab62021-05-28 12:06:34 +02002942 if k8s_instance_info.get("kdu-deployment-name"):
2943 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
2944 else:
2945 kdu_instance = self.k8scluster_map[
2946 k8sclustertype
2947 ].generate_kdu_instance_name(
2948 db_dict=db_dict_install,
2949 kdu_model=k8s_instance_info["kdu-model"],
2950 kdu_name=k8s_instance_info["kdu-name"],
2951 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002952 self.update_db_2(
2953 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2954 )
David Garciad64e2742021-02-25 20:19:18 +01002955 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00002956 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2957 kdu_model=k8s_instance_info["kdu-model"],
2958 atomic=True,
2959 params=k8params,
2960 db_dict=db_dict_install,
2961 timeout=timeout,
2962 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01002963 namespace=k8s_instance_info["namespace"],
2964 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02002965 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01002966 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002967 self.update_db_2(
2968 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2969 )
lloretgalleg7c121132020-07-08 07:53:22 +00002970
2971 # Obtain services to obtain management service ip
2972 services = await self.k8scluster_map[k8sclustertype].get_services(
2973 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2974 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01002975 namespace=k8s_instance_info["namespace"],
2976 )
lloretgalleg7c121132020-07-08 07:53:22 +00002977
2978 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00002979 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03002980 kdu_config = get_configuration(vnfd, kdud["name"])
2981 if kdu_config:
2982 target_ee_list = kdu_config.get("execution-environment-list", [])
2983 else:
2984 target_ee_list = []
2985
lloretgalleg7c121132020-07-08 07:53:22 +00002986 if services:
tierno7ecbc342020-09-21 14:05:39 +00002987 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01002988 mgmt_services = [
2989 service
2990 for service in kdud.get("service", [])
2991 if service.get("mgmt-service")
2992 ]
lloretgalleg7c121132020-07-08 07:53:22 +00002993 for mgmt_service in mgmt_services:
2994 for service in services:
2995 if service["name"].startswith(mgmt_service["name"]):
2996 # Mgmt service found, Obtain service ip
2997 ip = service.get("external_ip", service.get("cluster_ip"))
2998 if isinstance(ip, list) and len(ip) == 1:
2999 ip = ip[0]
3000
garciadeblas5697b8b2021-03-24 09:17:02 +01003001 vnfr_update_dict[
3002 "kdur.{}.ip-address".format(kdu_index)
3003 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003004
3005 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01003006 service_external_cp = mgmt_service.get(
3007 "external-connection-point-ref"
3008 )
lloretgalleg7c121132020-07-08 07:53:22 +00003009 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01003010 if (
3011 deep_get(vnfd, ("mgmt-interface", "cp"))
3012 == service_external_cp
3013 ):
lloretgalleg7c121132020-07-08 07:53:22 +00003014 vnfr_update_dict["ip-address"] = ip
3015
bravof6ec62b72021-02-25 17:20:35 -03003016 if find_in_list(
3017 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01003018 lambda ee: ee.get(
3019 "external-connection-point-ref", ""
3020 )
3021 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03003022 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01003023 vnfr_update_dict[
3024 "kdur.{}.ip-address".format(kdu_index)
3025 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00003026 break
3027 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003028 self.logger.warn(
3029 "Mgmt service name: {} not found".format(
3030 mgmt_service["name"]
3031 )
3032 )
lloretgalleg7c121132020-07-08 07:53:22 +00003033
tierno7ecbc342020-09-21 14:05:39 +00003034 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
3035 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00003036
bravof9a256db2021-02-22 18:02:07 -03003037 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01003038 if (
3039 kdu_config
3040 and kdu_config.get("initial-config-primitive")
3041 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
3042 ):
3043 initial_config_primitive_list = kdu_config.get(
3044 "initial-config-primitive"
3045 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003046 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
3047
3048 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003049 primitive_params_ = self._map_primitive_params(
3050 initial_config_primitive, {}, {}
3051 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003052
3053 await asyncio.wait_for(
3054 self.k8scluster_map[k8sclustertype].exec_primitive(
3055 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
3056 kdu_instance=kdu_instance,
3057 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01003058 params=primitive_params_,
3059 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02003060 vca_id=vca_id,
3061 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01003062 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02003063 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02003064
tiernob9018152020-04-16 14:18:24 +00003065 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00003066 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00003067 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003068 self.update_db_2(
3069 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3070 )
3071 self.update_db_2(
3072 "vnfrs",
3073 vnfr_data.get("_id"),
3074 {"kdur.{}.status".format(kdu_index): "ERROR"},
3075 )
tiernob9018152020-04-16 14:18:24 +00003076 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003077 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003078 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003079 # reraise original error
3080 raise
3081
3082 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003083
garciadeblas5697b8b2021-03-24 09:17:02 +01003084 async def deploy_kdus(
3085 self,
3086 logging_text,
3087 nsr_id,
3088 nslcmop_id,
3089 db_vnfrs,
3090 db_vnfds,
3091 task_instantiation_info,
3092 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003093 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003094
garciadeblas5697b8b2021-03-24 09:17:02 +01003095 k8scluster_id_2_uuic = {
3096 "helm-chart-v3": {},
3097 "helm-chart": {},
3098 "juju-bundle": {},
3099 }
tierno626e0152019-11-29 14:16:16 +00003100
tierno16f4a4e2020-07-20 09:05:51 +00003101 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003102 nonlocal k8scluster_id_2_uuic
3103 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3104 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3105
tierno16f4a4e2020-07-20 09:05:51 +00003106 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003107 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3108 "k8scluster", cluster_id
3109 )
tierno16f4a4e2020-07-20 09:05:51 +00003110 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003111 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3112 task_name, cluster_id
3113 )
tierno16f4a4e2020-07-20 09:05:51 +00003114 self.logger.debug(logging_text + text)
3115 await asyncio.wait(task_dependency, timeout=3600)
3116
garciadeblas5697b8b2021-03-24 09:17:02 +01003117 db_k8scluster = self.db.get_one(
3118 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3119 )
tierno626e0152019-11-29 14:16:16 +00003120 if not db_k8scluster:
3121 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003122
tierno626e0152019-11-29 14:16:16 +00003123 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3124 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003125 if cluster_type == "helm-chart-v3":
3126 try:
3127 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003128 k8s_credentials = yaml.safe_dump(
3129 db_k8scluster.get("credentials")
3130 )
3131 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3132 k8s_credentials, reuse_cluster_uuid=cluster_id
3133 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003134 db_k8scluster_update = {}
3135 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3136 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003137 db_k8scluster_update[
3138 "_admin.helm-chart-v3.created"
3139 ] = uninstall_sw
3140 db_k8scluster_update[
3141 "_admin.helm-chart-v3.operationalState"
3142 ] = "ENABLED"
3143 self.update_db_2(
3144 "k8sclusters", cluster_id, db_k8scluster_update
3145 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003146 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003147 self.logger.error(
3148 logging_text
3149 + "error initializing helm-v3 cluster: {}".format(str(e))
3150 )
3151 raise LcmException(
3152 "K8s cluster '{}' has not been initialized for '{}'".format(
3153 cluster_id, cluster_type
3154 )
3155 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003156 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003157 raise LcmException(
3158 "K8s cluster '{}' has not been initialized for '{}'".format(
3159 cluster_id, cluster_type
3160 )
3161 )
tierno626e0152019-11-29 14:16:16 +00003162 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3163 return k8s_id
3164
3165 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003166 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003167 try:
tierno626e0152019-11-29 14:16:16 +00003168 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003169 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003170
tierno626e0152019-11-29 14:16:16 +00003171 index = 0
tiernoe876f672020-02-13 14:34:48 +00003172 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003173 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003174
tierno626e0152019-11-29 14:16:16 +00003175 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003176 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003177 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3178 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003179 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003180 vnfd_id = vnfr_data.get("vnfd-id")
3181 vnfd_with_id = find_in_list(
3182 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3183 )
3184 kdud = next(
3185 kdud
3186 for kdud in vnfd_with_id["kdu"]
3187 if kdud["name"] == kdur["kdu-name"]
3188 )
tiernode1584f2020-04-07 09:07:33 +00003189 namespace = kdur.get("k8s-namespace")
romeromonser4e71ab62021-05-28 12:06:34 +02003190 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003191 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003192 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003193 # Default version: helm3, if helm-version is v2 assign v2
3194 k8sclustertype = "helm-chart-v3"
3195 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003196 if (
3197 kdur.get("helm-version")
3198 and kdur.get("helm-version") == "v2"
3199 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003200 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003201 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003202 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003203 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003204 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003205 raise LcmException(
3206 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3207 "juju-bundle. Maybe an old NBI version is running".format(
3208 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3209 )
3210 )
quilesjacde94f2020-01-23 10:07:08 +00003211 # check if kdumodel is a file and exists
3212 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003213 vnfd_with_id = find_in_list(
3214 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3215 )
3216 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
3217 if storage and storage.get(
3218 "pkg-dir"
3219 ): # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003220 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
garciadeblas5697b8b2021-03-24 09:17:02 +01003221 filename = "{}/{}/{}s/{}".format(
3222 storage["folder"],
3223 storage["pkg-dir"],
3224 k8sclustertype,
3225 kdumodel,
3226 )
3227 if self.fs.file_exists(
3228 filename, mode="file"
3229 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003230 kdumodel = self.fs.path + filename
3231 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003232 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003233 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003234 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003235
tiernoe876f672020-02-13 14:34:48 +00003236 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003237 step = "Synchronize repos for k8s cluster '{}'".format(
3238 k8s_cluster_id
3239 )
tierno16f4a4e2020-07-20 09:05:51 +00003240 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003241
lloretgalleg7c121132020-07-08 07:53:22 +00003242 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003243 if (
3244 k8sclustertype == "helm-chart"
3245 and cluster_uuid not in updated_cluster_list
3246 ) or (
3247 k8sclustertype == "helm-chart-v3"
3248 and cluster_uuid not in updated_v3_cluster_list
3249 ):
tiernoe876f672020-02-13 14:34:48 +00003250 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003251 self.k8scluster_map[k8sclustertype].synchronize_repos(
3252 cluster_uuid=cluster_uuid
3253 )
3254 )
tiernoe876f672020-02-13 14:34:48 +00003255 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003256 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003257 unset = {
3258 "_admin.helm_charts_added." + item: None
3259 for item in del_repo_list
3260 }
3261 updated = {
3262 "_admin.helm_charts_added." + item: name
3263 for item, name in added_repo_dict.items()
3264 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003265 updated_cluster_list.append(cluster_uuid)
3266 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003267 unset = {
3268 "_admin.helm_charts_v3_added." + item: None
3269 for item in del_repo_list
3270 }
3271 updated = {
3272 "_admin.helm_charts_v3_added." + item: name
3273 for item, name in added_repo_dict.items()
3274 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003275 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003276 self.logger.debug(
3277 logging_text + "repos synchronized on k8s cluster "
3278 "'{}' to_delete: {}, to_add: {}".format(
3279 k8s_cluster_id, del_repo_list, added_repo_dict
3280 )
3281 )
3282 self.db.set_one(
3283 "k8sclusters",
3284 {"_id": k8s_cluster_id},
3285 updated,
3286 unset=unset,
3287 )
lloretgallegedc5f332020-02-20 11:50:50 +01003288
lloretgalleg7c121132020-07-08 07:53:22 +00003289 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003290 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3291 vnfr_data["member-vnf-index-ref"],
3292 kdur["kdu-name"],
3293 k8s_cluster_id,
3294 )
3295 k8s_instance_info = {
3296 "kdu-instance": None,
3297 "k8scluster-uuid": cluster_uuid,
3298 "k8scluster-type": k8sclustertype,
3299 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3300 "kdu-name": kdur["kdu-name"],
3301 "kdu-model": kdumodel,
3302 "namespace": namespace,
romeromonser4e71ab62021-05-28 12:06:34 +02003303 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003304 }
tiernob9018152020-04-16 14:18:24 +00003305 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003306 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003307 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003308 vnfd_with_id = find_in_list(
3309 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3310 )
tiernoa2143262020-03-27 16:20:40 +00003311 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003312 self._install_kdu(
3313 nsr_id,
3314 db_path,
3315 vnfr_data,
3316 kdu_index,
3317 kdud,
3318 vnfd_with_id,
3319 k8s_instance_info,
3320 k8params=desc_params,
3321 timeout=600,
3322 vca_id=vca_id,
3323 )
3324 )
3325 self.lcm_tasks.register(
3326 "ns",
3327 nsr_id,
3328 nslcmop_id,
3329 "instantiate_KDU-{}".format(index),
3330 task,
3331 )
3332 task_instantiation_info[task] = "Deploying KDU {}".format(
3333 kdur["kdu-name"]
3334 )
tiernoe876f672020-02-13 14:34:48 +00003335
tierno626e0152019-11-29 14:16:16 +00003336 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003337
tiernoe876f672020-02-13 14:34:48 +00003338 except (LcmException, asyncio.CancelledError):
3339 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003340 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003341 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3342 if isinstance(e, (N2VCException, DbException)):
3343 self.logger.error(logging_text + msg)
3344 else:
3345 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003346 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003347 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003348 if db_nsr_update:
3349 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003350
garciadeblas5697b8b2021-03-24 09:17:02 +01003351 def _deploy_n2vc(
3352 self,
3353 logging_text,
3354 db_nsr,
3355 db_vnfr,
3356 nslcmop_id,
3357 nsr_id,
3358 nsi_id,
3359 vnfd_id,
3360 vdu_id,
3361 kdu_name,
3362 member_vnf_index,
3363 vdu_index,
3364 vdu_name,
3365 deploy_params,
3366 descriptor_config,
3367 base_folder,
3368 task_instantiation_info,
3369 stage,
3370 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003371 # launch instantiate_N2VC in a asyncio task and register task object
3372 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3373 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003374 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003375
garciadeblas5697b8b2021-03-24 09:17:02 +01003376 self.logger.debug(
3377 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3378 )
bravof9a256db2021-02-22 18:02:07 -03003379 if "execution-environment-list" in descriptor_config:
3380 ee_list = descriptor_config.get("execution-environment-list", [])
David Garciab76442a2021-05-28 12:08:18 +02003381 elif "juju" in descriptor_config:
3382 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003383 else: # other types as script are not supported
3384 ee_list = []
3385
3386 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003387 self.logger.debug(
3388 logging_text
3389 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3390 ee_item.get("juju"), ee_item.get("helm-chart")
3391 )
3392 )
tiernoa278b842020-07-08 15:33:55 +00003393 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003394 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003395 vca_name = ee_item["juju"].get("charm")
3396 vca_type = (
3397 "lxc_proxy_charm"
3398 if ee_item["juju"].get("charm") is not None
3399 else "native_charm"
3400 )
3401 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003402 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003403 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003404 vca_type = "native_charm"
3405 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003406 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003407 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3408 vca_type = "helm"
3409 else:
3410 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003411 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003412 self.logger.debug(
3413 logging_text + "skipping non juju neither charm configuration"
3414 )
quilesj7e13aeb2019-10-08 13:34:55 +02003415 continue
quilesj3655ae02019-12-12 16:08:35 +00003416
tierno588547c2020-07-01 15:30:20 +00003417 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003418 for vca_index, vca_deployed in enumerate(
3419 db_nsr["_admin"]["deployed"]["VCA"]
3420 ):
tierno588547c2020-07-01 15:30:20 +00003421 if not vca_deployed:
3422 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003423 if (
3424 vca_deployed.get("member-vnf-index") == member_vnf_index
3425 and vca_deployed.get("vdu_id") == vdu_id
3426 and vca_deployed.get("kdu_name") == kdu_name
3427 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3428 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3429 ):
tierno588547c2020-07-01 15:30:20 +00003430 break
3431 else:
3432 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003433 target = (
3434 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3435 )
tiernoa278b842020-07-08 15:33:55 +00003436 if vdu_id:
3437 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3438 elif kdu_name:
3439 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003440 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003441 "target_element": target,
3442 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003443 "member-vnf-index": member_vnf_index,
3444 "vdu_id": vdu_id,
3445 "kdu_name": kdu_name,
3446 "vdu_count_index": vdu_index,
3447 "operational-status": "init", # TODO revise
3448 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003449 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003450 "vnfd_id": vnfd_id,
3451 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003452 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003453 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003454 }
3455 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003456
tierno588547c2020-07-01 15:30:20 +00003457 # create VCA and configurationStatus in db
3458 db_dict = {
3459 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003460 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003461 }
3462 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003463
tierno588547c2020-07-01 15:30:20 +00003464 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3465
bravof922c4172020-11-24 21:21:43 -03003466 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3467 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3468 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3469
tierno588547c2020-07-01 15:30:20 +00003470 # Launch task
3471 task_n2vc = asyncio.ensure_future(
3472 self.instantiate_N2VC(
3473 logging_text=logging_text,
3474 vca_index=vca_index,
3475 nsi_id=nsi_id,
3476 db_nsr=db_nsr,
3477 db_vnfr=db_vnfr,
3478 vdu_id=vdu_id,
3479 kdu_name=kdu_name,
3480 vdu_index=vdu_index,
3481 deploy_params=deploy_params,
3482 config_descriptor=descriptor_config,
3483 base_folder=base_folder,
3484 nslcmop_id=nslcmop_id,
3485 stage=stage,
3486 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003487 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003488 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003489 )
quilesj7e13aeb2019-10-08 13:34:55 +02003490 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003491 self.lcm_tasks.register(
3492 "ns",
3493 nsr_id,
3494 nslcmop_id,
3495 "instantiate_N2VC-{}".format(vca_index),
3496 task_n2vc,
3497 )
3498 task_instantiation_info[
3499 task_n2vc
3500 ] = self.task_name_deploy_vca + " {}.{}".format(
3501 member_vnf_index or "", vdu_id or ""
3502 )
tiernobaa51102018-12-14 13:16:18 +00003503
tiernoc9556972019-07-05 15:25:25 +00003504 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003505 def _create_nslcmop(nsr_id, operation, params):
3506 """
3507 Creates a ns-lcm-opp content to be stored at database.
3508 :param nsr_id: internal id of the instance
3509 :param operation: instantiate, terminate, scale, action, ...
3510 :param params: user parameters for the operation
3511 :return: dictionary following SOL005 format
3512 """
3513 # Raise exception if invalid arguments
3514 if not (nsr_id and operation and params):
3515 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003516 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3517 )
kuuse0ca67472019-05-13 15:59:27 +02003518 now = time()
3519 _id = str(uuid4())
3520 nslcmop = {
3521 "id": _id,
3522 "_id": _id,
3523 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3524 "operationState": "PROCESSING",
3525 "statusEnteredTime": now,
3526 "nsInstanceId": nsr_id,
3527 "lcmOperationType": operation,
3528 "startTime": now,
3529 "isAutomaticInvocation": False,
3530 "operationParams": params,
3531 "isCancelPending": False,
3532 "links": {
3533 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3534 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003535 },
kuuse0ca67472019-05-13 15:59:27 +02003536 }
3537 return nslcmop
3538
calvinosanch9f9c6f22019-11-04 13:37:39 +01003539 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003540 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003541 for key, value in params.items():
3542 if str(value).startswith("!!yaml "):
3543 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003544 return params
3545
kuuse8b998e42019-07-30 15:22:16 +02003546 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003547 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003548 primitive_params = {}
3549 params = {
3550 "member_vnf_index": vnf_index,
3551 "primitive": primitive,
3552 "primitive_params": primitive_params,
3553 }
3554 desc_params = {}
3555 return self._map_primitive_params(seq, params, desc_params)
3556
kuuseac3a8882019-10-03 10:48:06 +02003557 # sub-operations
3558
tierno51183952020-04-03 15:48:18 +00003559 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003560 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3561 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003562 # b. Skip sub-operation
3563 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3564 return self.SUBOPERATION_STATUS_SKIP
3565 else:
tierno7c4e24c2020-05-13 08:41:35 +00003566 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003567 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003568 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003569 operationState = "PROCESSING"
3570 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003571 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003572 db_nslcmop, op_index, operationState, detailed_status
3573 )
kuuseac3a8882019-10-03 10:48:06 +02003574 # Return the sub-operation index
3575 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3576 # with arguments extracted from the sub-operation
3577 return op_index
3578
3579 # Find a sub-operation where all keys in a matching dictionary must match
3580 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3581 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003582 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003583 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003584 for i, op in enumerate(op_list):
3585 if all(op.get(k) == match[k] for k in match):
3586 return i
3587 return self.SUBOPERATION_STATUS_NOT_FOUND
3588
3589 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003590 def _update_suboperation_status(
3591 self, db_nslcmop, op_index, operationState, detailed_status
3592 ):
kuuseac3a8882019-10-03 10:48:06 +02003593 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003594 q_filter = {"_id": db_nslcmop["_id"]}
3595 update_dict = {
3596 "_admin.operations.{}.operationState".format(op_index): operationState,
3597 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3598 }
3599 self.db.set_one(
3600 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3601 )
kuuseac3a8882019-10-03 10:48:06 +02003602
3603 # Add sub-operation, return the index of the added sub-operation
3604 # Optionally, set operationState, detailed-status, and operationType
3605 # Status and type are currently set for 'scale' sub-operations:
3606 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3607 # 'detailed-status' : status message
3608 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3609 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003610 def _add_suboperation(
3611 self,
3612 db_nslcmop,
3613 vnf_index,
3614 vdu_id,
3615 vdu_count_index,
3616 vdu_name,
3617 primitive,
3618 mapped_primitive_params,
3619 operationState=None,
3620 detailed_status=None,
3621 operationType=None,
3622 RO_nsr_id=None,
3623 RO_scaling_info=None,
3624 ):
tiernoe876f672020-02-13 14:34:48 +00003625 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003626 return self.SUBOPERATION_STATUS_NOT_FOUND
3627 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003628 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3629 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003630 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003631 new_op = {
3632 "member_vnf_index": vnf_index,
3633 "vdu_id": vdu_id,
3634 "vdu_count_index": vdu_count_index,
3635 "primitive": primitive,
3636 "primitive_params": mapped_primitive_params,
3637 }
kuuseac3a8882019-10-03 10:48:06 +02003638 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003639 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003640 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003641 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003642 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003643 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003644 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003645 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003646 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003647 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003648 if not op_list:
3649 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003650 db_nslcmop_admin.update({"operations": [new_op]})
3651 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003652 else:
3653 # Existing operations, append operation to list
3654 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003655
garciadeblas5697b8b2021-03-24 09:17:02 +01003656 db_nslcmop_update = {"_admin.operations": op_list}
3657 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003658 op_index = len(op_list) - 1
3659 return op_index
3660
3661 # Helper methods for scale() sub-operations
3662
3663 # pre-scale/post-scale:
3664 # Check for 3 different cases:
3665 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3666 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003667 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003668 def _check_or_add_scale_suboperation(
3669 self,
3670 db_nslcmop,
3671 vnf_index,
3672 vnf_config_primitive,
3673 primitive_params,
3674 operationType,
3675 RO_nsr_id=None,
3676 RO_scaling_info=None,
3677 ):
kuuseac3a8882019-10-03 10:48:06 +02003678 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003679 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003680 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003681 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003682 "member_vnf_index": vnf_index,
3683 "RO_nsr_id": RO_nsr_id,
3684 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003685 }
3686 else:
3687 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003688 "member_vnf_index": vnf_index,
3689 "primitive": vnf_config_primitive,
3690 "primitive_params": primitive_params,
3691 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003692 }
3693 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003694 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003695 # a. New sub-operation
3696 # The sub-operation does not exist, add it.
3697 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3698 # The following parameters are set to None for all kind of scaling:
3699 vdu_id = None
3700 vdu_count_index = None
3701 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003702 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003703 vnf_config_primitive = None
3704 primitive_params = None
3705 else:
3706 RO_nsr_id = None
3707 RO_scaling_info = None
3708 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003709 operationState = "PROCESSING"
3710 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003711 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01003712 self._add_suboperation(
3713 db_nslcmop,
3714 vnf_index,
3715 vdu_id,
3716 vdu_count_index,
3717 vdu_name,
3718 vnf_config_primitive,
3719 primitive_params,
3720 operationState,
3721 detailed_status,
3722 operationType,
3723 RO_nsr_id,
3724 RO_scaling_info,
3725 )
kuuseac3a8882019-10-03 10:48:06 +02003726 return self.SUBOPERATION_STATUS_NEW
3727 else:
3728 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
3729 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00003730 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02003731
preethika.pdf7d8e02019-12-10 13:10:48 +00003732 # Function to return execution_environment id
3733
3734 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00003735 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00003736 for vca in vca_deployed_list:
3737 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
3738 return vca["ee_id"]
3739
David Garciac1fe90a2021-03-31 19:12:02 +02003740 async def destroy_N2VC(
3741 self,
3742 logging_text,
3743 db_nslcmop,
3744 vca_deployed,
3745 config_descriptor,
3746 vca_index,
3747 destroy_ee=True,
3748 exec_primitives=True,
3749 scaling_in=False,
3750 vca_id: str = None,
3751 ):
tiernoe876f672020-02-13 14:34:48 +00003752 """
3753 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
3754 :param logging_text:
3755 :param db_nslcmop:
3756 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
3757 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
3758 :param vca_index: index in the database _admin.deployed.VCA
3759 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00003760 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
3761 not executed properly
aktas13251562021-02-12 22:19:10 +03003762 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00003763 :return: None or exception
3764 """
tiernoe876f672020-02-13 14:34:48 +00003765
tierno588547c2020-07-01 15:30:20 +00003766 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01003767 logging_text
3768 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00003769 vca_index, vca_deployed, config_descriptor, destroy_ee
3770 )
3771 )
3772
3773 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
3774
3775 # execute terminate_primitives
3776 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03003777 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01003778 config_descriptor.get("terminate-config-primitive"),
3779 vca_deployed.get("ee_descriptor_id"),
3780 )
tierno588547c2020-07-01 15:30:20 +00003781 vdu_id = vca_deployed.get("vdu_id")
3782 vdu_count_index = vca_deployed.get("vdu_count_index")
3783 vdu_name = vca_deployed.get("vdu_name")
3784 vnf_index = vca_deployed.get("member-vnf-index")
3785 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00003786 for seq in terminate_primitives:
3787 # For each sequence in list, get primitive and call _ns_execute_primitive()
3788 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01003789 vnf_index, seq.get("name")
3790 )
tierno588547c2020-07-01 15:30:20 +00003791 self.logger.debug(logging_text + step)
3792 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01003793 primitive = seq.get("name")
3794 mapped_primitive_params = self._get_terminate_primitive_params(
3795 seq, vnf_index
3796 )
tierno588547c2020-07-01 15:30:20 +00003797
3798 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003799 self._add_suboperation(
3800 db_nslcmop,
3801 vnf_index,
3802 vdu_id,
3803 vdu_count_index,
3804 vdu_name,
3805 primitive,
3806 mapped_primitive_params,
3807 )
tierno588547c2020-07-01 15:30:20 +00003808 # Sub-operations: Call _ns_execute_primitive() instead of action()
3809 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003810 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01003811 vca_deployed["ee_id"],
3812 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02003813 mapped_primitive_params,
3814 vca_type=vca_type,
3815 vca_id=vca_id,
3816 )
tierno588547c2020-07-01 15:30:20 +00003817 except LcmException:
3818 # this happens when VCA is not deployed. In this case it is not needed to terminate
3819 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003820 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00003821 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01003822 raise LcmException(
3823 "terminate_primitive {} for vnf_member_index={} fails with "
3824 "error {}".format(seq.get("name"), vnf_index, result_detail)
3825 )
tierno588547c2020-07-01 15:30:20 +00003826 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01003827 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
3828 vca_index
3829 )
3830 self.update_db_2(
3831 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
3832 )
tiernoe876f672020-02-13 14:34:48 +00003833
tiernob996d942020-07-03 14:52:28 +00003834 if vca_deployed.get("prometheus_jobs") and self.prometheus:
3835 await self.prometheus.update(remove_jobs=vca_deployed["prometheus_jobs"])
3836
tiernoe876f672020-02-13 14:34:48 +00003837 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02003838 await self.vca_map[vca_type].delete_execution_environment(
3839 vca_deployed["ee_id"],
3840 scaling_in=scaling_in,
aktas730569b2021-07-29 17:42:49 +03003841 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02003842 vca_id=vca_id,
3843 )
kuuse0ca67472019-05-13 15:59:27 +02003844
David Garciac1fe90a2021-03-31 19:12:02 +02003845 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01003846 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00003847 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00003848 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003849 await self.n2vc.delete_namespace(
3850 namespace=namespace,
3851 total_timeout=self.timeout_charm_delete,
3852 vca_id=vca_id,
3853 )
tiernof59ad6c2020-04-08 12:50:52 +00003854 except N2VCNotFound: # already deleted. Skip
3855 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01003856 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00003857
garciadeblas5697b8b2021-03-24 09:17:02 +01003858 async def _terminate_RO(
3859 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
3860 ):
tiernoe876f672020-02-13 14:34:48 +00003861 """
3862 Terminates a deployment from RO
3863 :param logging_text:
3864 :param nsr_deployed: db_nsr._admin.deployed
3865 :param nsr_id:
3866 :param nslcmop_id:
3867 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
3868 this method will update only the index 2, but it will write on database the concatenated content of the list
3869 :return:
3870 """
3871 db_nsr_update = {}
3872 failed_detail = []
3873 ro_nsr_id = ro_delete_action = None
3874 if nsr_deployed and nsr_deployed.get("RO"):
3875 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
3876 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
3877 try:
3878 if ro_nsr_id:
3879 stage[2] = "Deleting ns from VIM."
3880 db_nsr_update["detailed-status"] = " ".join(stage)
3881 self._write_op_status(nslcmop_id, stage)
3882 self.logger.debug(logging_text + stage[2])
3883 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3884 self._write_op_status(nslcmop_id, stage)
3885 desc = await self.RO.delete("ns", ro_nsr_id)
3886 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003887 db_nsr_update[
3888 "_admin.deployed.RO.nsr_delete_action_id"
3889 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00003890 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3891 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3892 if ro_delete_action:
3893 # wait until NS is deleted from VIM
3894 stage[2] = "Waiting ns deleted from VIM."
3895 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003896 self.logger.debug(
3897 logging_text
3898 + stage[2]
3899 + " RO_id={} ro_delete_action={}".format(
3900 ro_nsr_id, ro_delete_action
3901 )
3902 )
tiernoe876f672020-02-13 14:34:48 +00003903 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3904 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02003905
tiernoe876f672020-02-13 14:34:48 +00003906 delete_timeout = 20 * 60 # 20 minutes
3907 while delete_timeout > 0:
3908 desc = await self.RO.show(
3909 "ns",
3910 item_id_name=ro_nsr_id,
3911 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01003912 extra_item_id=ro_delete_action,
3913 )
tiernoe876f672020-02-13 14:34:48 +00003914
3915 # deploymentStatus
3916 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
3917
3918 ns_status, ns_status_info = self.RO.check_action_status(desc)
3919 if ns_status == "ERROR":
3920 raise ROclient.ROClientException(ns_status_info)
3921 elif ns_status == "BUILD":
3922 stage[2] = "Deleting from VIM {}".format(ns_status_info)
3923 elif ns_status == "ACTIVE":
3924 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
3925 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3926 break
3927 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003928 assert (
3929 False
3930 ), "ROclient.check_action_status returns unknown {}".format(
3931 ns_status
3932 )
tiernoe876f672020-02-13 14:34:48 +00003933 if stage[2] != detailed_status_old:
3934 detailed_status_old = stage[2]
3935 db_nsr_update["detailed-status"] = " ".join(stage)
3936 self._write_op_status(nslcmop_id, stage)
3937 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3938 await asyncio.sleep(5, loop=self.loop)
3939 delete_timeout -= 5
3940 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01003941 raise ROclient.ROClientException(
3942 "Timeout waiting ns deleted from VIM"
3943 )
tiernoe876f672020-02-13 14:34:48 +00003944
3945 except Exception as e:
3946 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003947 if (
3948 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3949 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003950 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3951 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3952 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003953 self.logger.debug(
3954 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
3955 )
3956 elif (
3957 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3958 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00003959 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003960 self.logger.debug(
3961 logging_text
3962 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
3963 )
tiernoe876f672020-02-13 14:34:48 +00003964 else:
tiernoa2143262020-03-27 16:20:40 +00003965 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003966 self.logger.error(
3967 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
3968 )
tiernoe876f672020-02-13 14:34:48 +00003969
3970 # Delete nsd
3971 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
3972 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
3973 try:
3974 stage[2] = "Deleting nsd from RO."
3975 db_nsr_update["detailed-status"] = " ".join(stage)
3976 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3977 self._write_op_status(nslcmop_id, stage)
3978 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01003979 self.logger.debug(
3980 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
3981 )
tiernoe876f672020-02-13 14:34:48 +00003982 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
3983 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003984 if (
3985 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3986 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003987 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003988 self.logger.debug(
3989 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
3990 )
3991 elif (
3992 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3993 ): # conflict
3994 failed_detail.append(
3995 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
3996 )
tiernoe876f672020-02-13 14:34:48 +00003997 self.logger.debug(logging_text + failed_detail[-1])
3998 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003999 failed_detail.append(
4000 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
4001 )
tiernoe876f672020-02-13 14:34:48 +00004002 self.logger.error(logging_text + failed_detail[-1])
4003
4004 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
4005 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
4006 if not vnf_deployed or not vnf_deployed["id"]:
4007 continue
4008 try:
4009 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004010 stage[
4011 2
4012 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
4013 vnf_deployed["member-vnf-index"], ro_vnfd_id
4014 )
tiernoe876f672020-02-13 14:34:48 +00004015 db_nsr_update["detailed-status"] = " ".join(stage)
4016 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4017 self._write_op_status(nslcmop_id, stage)
4018 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004019 self.logger.debug(
4020 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
4021 )
tiernoe876f672020-02-13 14:34:48 +00004022 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
4023 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004024 if (
4025 isinstance(e, ROclient.ROClientException) and e.http_code == 404
4026 ): # not found
4027 db_nsr_update[
4028 "_admin.deployed.RO.vnfd.{}.id".format(index)
4029 ] = None
4030 self.logger.debug(
4031 logging_text
4032 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
4033 )
4034 elif (
4035 isinstance(e, ROclient.ROClientException) and e.http_code == 409
4036 ): # conflict
4037 failed_detail.append(
4038 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
4039 )
tiernoe876f672020-02-13 14:34:48 +00004040 self.logger.debug(logging_text + failed_detail[-1])
4041 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004042 failed_detail.append(
4043 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
4044 )
tiernoe876f672020-02-13 14:34:48 +00004045 self.logger.error(logging_text + failed_detail[-1])
4046
tiernoa2143262020-03-27 16:20:40 +00004047 if failed_detail:
4048 stage[2] = "Error deleting from VIM"
4049 else:
4050 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00004051 db_nsr_update["detailed-status"] = " ".join(stage)
4052 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4053 self._write_op_status(nslcmop_id, stage)
4054
4055 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00004056 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00004057
4058 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004059 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004060 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004061 if not task_is_locked_by_me:
4062 return
4063
tierno59d22d22018-09-25 18:10:19 +02004064 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
4065 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00004066 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02004067 db_nsr = None
4068 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00004069 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004070 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004071 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004072 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004073 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004074 tasks_dict_info = {}
4075 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004076 stage = [
4077 "Stage 1/3: Preparing task.",
4078 "Waiting for previous operations to terminate.",
4079 "",
4080 ]
tiernoe876f672020-02-13 14:34:48 +00004081 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004082 try:
kuused124bfe2019-06-18 12:09:24 +02004083 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004084 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004085
tiernoe876f672020-02-13 14:34:48 +00004086 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4087 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4088 operation_params = db_nslcmop.get("operationParams") or {}
4089 if operation_params.get("timeout_ns_terminate"):
4090 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4091 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4092 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4093
4094 db_nsr_update["operational-status"] = "terminating"
4095 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004096 self._write_ns_status(
4097 nsr_id=nsr_id,
4098 ns_state="TERMINATING",
4099 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004100 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004101 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004102 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004103 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004104 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004105 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4106 return
tierno59d22d22018-09-25 18:10:19 +02004107
tiernoe876f672020-02-13 14:34:48 +00004108 stage[1] = "Getting vnf descriptors from db."
4109 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004110 db_vnfrs_dict = {
4111 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4112 }
tiernoe876f672020-02-13 14:34:48 +00004113 db_vnfds_from_id = {}
4114 db_vnfds_from_member_index = {}
4115 # Loop over VNFRs
4116 for vnfr in db_vnfrs_list:
4117 vnfd_id = vnfr["vnfd-id"]
4118 if vnfd_id not in db_vnfds_from_id:
4119 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4120 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004121 db_vnfds_from_member_index[
4122 vnfr["member-vnf-index-ref"]
4123 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004124
tiernoe876f672020-02-13 14:34:48 +00004125 # Destroy individual execution environments when there are terminating primitives.
4126 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004127 # TODO - check before calling _destroy_N2VC
4128 # if not operation_params.get("skip_terminate_primitives"):#
4129 # or not vca.get("needed_terminate"):
4130 stage[0] = "Stage 2/3 execute terminating primitives."
4131 self.logger.debug(logging_text + stage[0])
4132 stage[1] = "Looking execution environment that needs terminate."
4133 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004134
tierno588547c2020-07-01 15:30:20 +00004135 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004136 config_descriptor = None
David Garciab76442a2021-05-28 12:08:18 +02004137 vca_member_vnf_index = vca.get("member-vnf-index")
4138 vca_id = self.get_vca_id(
4139 db_vnfrs_dict.get(vca_member_vnf_index)
4140 if vca_member_vnf_index
4141 else None,
4142 db_nsr,
4143 )
tierno588547c2020-07-01 15:30:20 +00004144 if not vca or not vca.get("ee_id"):
4145 continue
4146 if not vca.get("member-vnf-index"):
4147 # ns
4148 config_descriptor = db_nsr.get("ns-configuration")
4149 elif vca.get("vdu_id"):
4150 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004151 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004152 elif vca.get("kdu_name"):
4153 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004154 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004155 else:
bravofe5a31bc2021-02-17 19:09:12 -03004156 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004157 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004158 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004159 exec_terminate_primitives = not operation_params.get(
4160 "skip_terminate_primitives"
4161 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004162 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4163 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004164 destroy_ee = (
4165 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4166 )
tierno86e33612020-09-16 14:13:06 +00004167 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4168 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004169 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004170 self.destroy_N2VC(
4171 logging_text,
4172 db_nslcmop,
4173 vca,
4174 config_descriptor,
4175 vca_index,
4176 destroy_ee,
4177 exec_terminate_primitives,
4178 vca_id=vca_id,
4179 )
4180 )
tierno588547c2020-07-01 15:30:20 +00004181 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004182
tierno588547c2020-07-01 15:30:20 +00004183 # wait for pending tasks of terminate primitives
4184 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004185 self.logger.debug(
4186 logging_text
4187 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4188 )
4189 error_list = await self._wait_for_tasks(
4190 logging_text,
4191 tasks_dict_info,
4192 min(self.timeout_charm_delete, timeout_ns_terminate),
4193 stage,
4194 nslcmop_id,
4195 )
tierno86e33612020-09-16 14:13:06 +00004196 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004197 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004198 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004199
tiernoe876f672020-02-13 14:34:48 +00004200 # remove All execution environments at once
4201 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004202
tierno49676be2020-04-07 16:34:35 +00004203 if nsr_deployed.get("VCA"):
4204 stage[1] = "Deleting all execution environments."
4205 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004206 vca_id = self.get_vca_id({}, db_nsr)
4207 task_delete_ee = asyncio.ensure_future(
4208 asyncio.wait_for(
4209 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004210 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004211 )
4212 )
tierno49676be2020-04-07 16:34:35 +00004213 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4214 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004215
tiernoe876f672020-02-13 14:34:48 +00004216 # Delete from k8scluster
4217 stage[1] = "Deleting KDUs."
4218 self.logger.debug(logging_text + stage[1])
4219 # print(nsr_deployed)
4220 for kdu in get_iterable(nsr_deployed, "K8s"):
4221 if not kdu or not kdu.get("kdu-instance"):
4222 continue
4223 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004224 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004225 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4226 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004227 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004228 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4229 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004230 kdu_instance=kdu_instance,
4231 vca_id=vca_id,
4232 )
4233 )
tiernoe876f672020-02-13 14:34:48 +00004234 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004235 self.logger.error(
4236 logging_text
4237 + "Unknown k8s deployment type {}".format(
4238 kdu.get("k8scluster-type")
4239 )
4240 )
tiernoe876f672020-02-13 14:34:48 +00004241 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004242 tasks_dict_info[
4243 task_delete_kdu_instance
4244 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004245
4246 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004247 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004248 if self.ng_ro:
4249 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004250 self._terminate_ng_ro(
4251 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4252 )
4253 )
tierno69f0d382020-05-07 13:08:09 +00004254 else:
4255 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004256 self._terminate_RO(
4257 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4258 )
4259 )
tiernoe876f672020-02-13 14:34:48 +00004260 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004261
tiernoe876f672020-02-13 14:34:48 +00004262 # rest of staff will be done at finally
4263
garciadeblas5697b8b2021-03-24 09:17:02 +01004264 except (
4265 ROclient.ROClientException,
4266 DbException,
4267 LcmException,
4268 N2VCException,
4269 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004270 self.logger.error(logging_text + "Exit Exception {}".format(e))
4271 exc = e
4272 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004273 self.logger.error(
4274 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4275 )
tiernoe876f672020-02-13 14:34:48 +00004276 exc = "Operation was cancelled"
4277 except Exception as e:
4278 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004279 self.logger.critical(
4280 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4281 exc_info=True,
4282 )
tiernoe876f672020-02-13 14:34:48 +00004283 finally:
4284 if exc:
4285 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004286 try:
tiernoe876f672020-02-13 14:34:48 +00004287 # wait for pending tasks
4288 if tasks_dict_info:
4289 stage[1] = "Waiting for terminate pending tasks."
4290 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004291 error_list += await self._wait_for_tasks(
4292 logging_text,
4293 tasks_dict_info,
4294 timeout_ns_terminate,
4295 stage,
4296 nslcmop_id,
4297 )
tiernoe876f672020-02-13 14:34:48 +00004298 stage[1] = stage[2] = ""
4299 except asyncio.CancelledError:
4300 error_list.append("Cancelled")
4301 # TODO cancell all tasks
4302 except Exception as exc:
4303 error_list.append(str(exc))
4304 # update status at database
4305 if error_list:
4306 error_detail = "; ".join(error_list)
4307 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004308 error_description_nslcmop = "{} Detail: {}".format(
4309 stage[0], error_detail
4310 )
4311 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4312 nslcmop_id, stage[0]
4313 )
tierno59d22d22018-09-25 18:10:19 +02004314
tierno59d22d22018-09-25 18:10:19 +02004315 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004316 db_nsr_update["detailed-status"] = (
4317 error_description_nsr + " Detail: " + error_detail
4318 )
tiernoe876f672020-02-13 14:34:48 +00004319 db_nslcmop_update["detailed-status"] = error_detail
4320 nslcmop_operation_state = "FAILED"
4321 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004322 else:
tiernoa2143262020-03-27 16:20:40 +00004323 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004324 error_description_nsr = error_description_nslcmop = None
4325 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004326 db_nsr_update["operational-status"] = "terminated"
4327 db_nsr_update["detailed-status"] = "Done"
4328 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4329 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004330 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004331
tiernoe876f672020-02-13 14:34:48 +00004332 if db_nsr:
4333 self._write_ns_status(
4334 nsr_id=nsr_id,
4335 ns_state=ns_state,
4336 current_operation="IDLE",
4337 current_operation_id=None,
4338 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004339 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004340 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004341 )
tiernoa17d4f42020-04-28 09:59:23 +00004342 self._write_op_status(
4343 op_id=nslcmop_id,
4344 stage="",
4345 error_message=error_description_nslcmop,
4346 operation_state=nslcmop_operation_state,
4347 other_update=db_nslcmop_update,
4348 )
lloretgalleg6d488782020-07-22 10:13:46 +00004349 if ns_state == "NOT_INSTANTIATED":
4350 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004351 self.db.set_list(
4352 "vnfrs",
4353 {"nsr-id-ref": nsr_id},
4354 {"_admin.nsState": "NOT_INSTANTIATED"},
4355 )
lloretgalleg6d488782020-07-22 10:13:46 +00004356 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004357 self.logger.warn(
4358 logging_text
4359 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4360 nsr_id, e
4361 )
4362 )
tiernoa17d4f42020-04-28 09:59:23 +00004363 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004364 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004365 if nslcmop_operation_state:
4366 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004367 await self.msg.aiowrite(
4368 "ns",
4369 "terminated",
4370 {
4371 "nsr_id": nsr_id,
4372 "nslcmop_id": nslcmop_id,
4373 "operationState": nslcmop_operation_state,
4374 "autoremove": autoremove,
4375 },
4376 loop=self.loop,
4377 )
tierno59d22d22018-09-25 18:10:19 +02004378 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004379 self.logger.error(
4380 logging_text + "kafka_write notification Exception {}".format(e)
4381 )
quilesj7e13aeb2019-10-08 13:34:55 +02004382
tierno59d22d22018-09-25 18:10:19 +02004383 self.logger.debug(logging_text + "Exit")
4384 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4385
garciadeblas5697b8b2021-03-24 09:17:02 +01004386 async def _wait_for_tasks(
4387 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4388 ):
tiernoe876f672020-02-13 14:34:48 +00004389 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004390 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004391 error_list = []
4392 pending_tasks = list(created_tasks_info.keys())
4393 num_tasks = len(pending_tasks)
4394 num_done = 0
4395 stage[1] = "{}/{}.".format(num_done, num_tasks)
4396 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004397 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004398 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004399 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004400 done, pending_tasks = await asyncio.wait(
4401 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4402 )
tiernoe876f672020-02-13 14:34:48 +00004403 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004404 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004405 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004406 new_error = created_tasks_info[task] + ": Timeout"
4407 error_detail_list.append(new_error)
4408 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004409 break
4410 for task in done:
4411 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004412 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004413 else:
4414 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004415 if exc:
4416 if isinstance(exc, asyncio.TimeoutError):
4417 exc = "Timeout"
4418 new_error = created_tasks_info[task] + ": {}".format(exc)
4419 error_list.append(created_tasks_info[task])
4420 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004421 if isinstance(
4422 exc,
4423 (
4424 str,
4425 DbException,
4426 N2VCException,
4427 ROclient.ROClientException,
4428 LcmException,
4429 K8sException,
4430 NgRoException,
4431 ),
4432 ):
tierno067e04a2020-03-31 12:53:13 +00004433 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004434 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004435 exc_traceback = "".join(
4436 traceback.format_exception(None, exc, exc.__traceback__)
4437 )
4438 self.logger.error(
4439 logging_text
4440 + created_tasks_info[task]
4441 + " "
4442 + exc_traceback
4443 )
tierno067e04a2020-03-31 12:53:13 +00004444 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004445 self.logger.debug(
4446 logging_text + created_tasks_info[task] + ": Done"
4447 )
tiernoe876f672020-02-13 14:34:48 +00004448 stage[1] = "{}/{}.".format(num_done, num_tasks)
4449 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004450 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004451 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004452 self.update_db_2(
4453 "nsrs",
4454 nsr_id,
4455 {
4456 "errorDescription": "Error at: " + ", ".join(error_list),
4457 "errorDetail": ". ".join(error_detail_list),
4458 },
4459 )
tiernoe876f672020-02-13 14:34:48 +00004460 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004461 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004462
tiernoda1ff8c2020-10-22 14:12:46 +00004463 @staticmethod
4464 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004465 """
4466 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4467 The default-value is used. If it is between < > it look for a value at instantiation_params
4468 :param primitive_desc: portion of VNFD/NSD that describes primitive
4469 :param params: Params provided by user
4470 :param instantiation_params: Instantiation params provided by user
4471 :return: a dictionary with the calculated params
4472 """
4473 calculated_params = {}
4474 for parameter in primitive_desc.get("parameter", ()):
4475 param_name = parameter["name"]
4476 if param_name in params:
4477 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004478 elif "default-value" in parameter or "value" in parameter:
4479 if "value" in parameter:
4480 calculated_params[param_name] = parameter["value"]
4481 else:
4482 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004483 if (
4484 isinstance(calculated_params[param_name], str)
4485 and calculated_params[param_name].startswith("<")
4486 and calculated_params[param_name].endswith(">")
4487 ):
tierno98ad6ea2019-05-30 17:16:28 +00004488 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004489 calculated_params[param_name] = instantiation_params[
4490 calculated_params[param_name][1:-1]
4491 ]
tiernoda964822019-01-14 15:53:47 +00004492 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004493 raise LcmException(
4494 "Parameter {} needed to execute primitive {} not provided".format(
4495 calculated_params[param_name], primitive_desc["name"]
4496 )
4497 )
tiernoda964822019-01-14 15:53:47 +00004498 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004499 raise LcmException(
4500 "Parameter {} needed to execute primitive {} not provided".format(
4501 param_name, primitive_desc["name"]
4502 )
4503 )
tierno59d22d22018-09-25 18:10:19 +02004504
tiernoda964822019-01-14 15:53:47 +00004505 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004506 calculated_params[param_name] = yaml.safe_dump(
4507 calculated_params[param_name], default_flow_style=True, width=256
4508 )
4509 elif isinstance(calculated_params[param_name], str) and calculated_params[
4510 param_name
4511 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004512 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004513 if parameter.get("data-type") == "INTEGER":
4514 try:
4515 calculated_params[param_name] = int(calculated_params[param_name])
4516 except ValueError: # error converting string to int
4517 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004518 "Parameter {} of primitive {} must be integer".format(
4519 param_name, primitive_desc["name"]
4520 )
4521 )
tiernofa40e692020-10-14 14:59:36 +00004522 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004523 calculated_params[param_name] = not (
4524 (str(calculated_params[param_name])).lower() == "false"
4525 )
tiernoc3f2a822019-11-05 13:45:04 +00004526
4527 # add always ns_config_info if primitive name is config
4528 if primitive_desc["name"] == "config":
4529 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004530 calculated_params["ns_config_info"] = instantiation_params[
4531 "ns_config_info"
4532 ]
tiernoda964822019-01-14 15:53:47 +00004533 return calculated_params
4534
garciadeblas5697b8b2021-03-24 09:17:02 +01004535 def _look_for_deployed_vca(
4536 self,
4537 deployed_vca,
4538 member_vnf_index,
4539 vdu_id,
4540 vdu_count_index,
4541 kdu_name=None,
4542 ee_descriptor_id=None,
4543 ):
tiernoe876f672020-02-13 14:34:48 +00004544 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4545 for vca in deployed_vca:
4546 if not vca:
4547 continue
4548 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4549 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004550 if (
4551 vdu_count_index is not None
4552 and vdu_count_index != vca["vdu_count_index"]
4553 ):
tiernoe876f672020-02-13 14:34:48 +00004554 continue
4555 if kdu_name and kdu_name != vca["kdu_name"]:
4556 continue
tiernoa278b842020-07-08 15:33:55 +00004557 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4558 continue
tiernoe876f672020-02-13 14:34:48 +00004559 break
4560 else:
4561 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004562 raise LcmException(
4563 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4564 " is not deployed".format(
4565 member_vnf_index,
4566 vdu_id,
4567 vdu_count_index,
4568 kdu_name,
4569 ee_descriptor_id,
4570 )
4571 )
tiernoe876f672020-02-13 14:34:48 +00004572 # get ee_id
4573 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004574 vca_type = vca.get(
4575 "type", "lxc_proxy_charm"
4576 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004577 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004578 raise LcmException(
4579 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4580 "execution environment".format(
4581 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4582 )
4583 )
tierno588547c2020-07-01 15:30:20 +00004584 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004585
David Garciac1fe90a2021-03-31 19:12:02 +02004586 async def _ns_execute_primitive(
4587 self,
4588 ee_id,
4589 primitive,
4590 primitive_params,
4591 retries=0,
4592 retries_interval=30,
4593 timeout=None,
4594 vca_type=None,
4595 db_dict=None,
4596 vca_id: str = None,
4597 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004598 try:
tierno98ad6ea2019-05-30 17:16:28 +00004599 if primitive == "config":
4600 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004601
tierno588547c2020-07-01 15:30:20 +00004602 vca_type = vca_type or "lxc_proxy_charm"
4603
quilesj7e13aeb2019-10-08 13:34:55 +02004604 while retries >= 0:
4605 try:
tierno067e04a2020-03-31 12:53:13 +00004606 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004607 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004608 ee_id=ee_id,
4609 primitive_name=primitive,
4610 params_dict=primitive_params,
4611 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004612 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004613 db_dict=db_dict,
4614 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03004615 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004616 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004617 timeout=timeout or self.timeout_primitive,
4618 )
quilesj7e13aeb2019-10-08 13:34:55 +02004619 # execution was OK
4620 break
tierno067e04a2020-03-31 12:53:13 +00004621 except asyncio.CancelledError:
4622 raise
4623 except Exception as e: # asyncio.TimeoutError
4624 if isinstance(e, asyncio.TimeoutError):
4625 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004626 retries -= 1
4627 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004628 self.logger.debug(
4629 "Error executing action {} on {} -> {}".format(
4630 primitive, ee_id, e
4631 )
4632 )
quilesj7e13aeb2019-10-08 13:34:55 +02004633 # wait and retry
4634 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004635 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004636 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004637
garciadeblas5697b8b2021-03-24 09:17:02 +01004638 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004639
tierno067e04a2020-03-31 12:53:13 +00004640 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004641 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004642 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004643 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004644
ksaikiranr3fde2c72021-03-15 10:39:06 +05304645 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4646 """
4647 Updating the vca_status with latest juju information in nsrs record
4648 :param: nsr_id: Id of the nsr
4649 :param: nslcmop_id: Id of the nslcmop
4650 :return: None
4651 """
4652
4653 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4654 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004655 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004656 if db_nsr["_admin"]["deployed"]["K8s"]:
4657 for k8s_index, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304658 cluster_uuid, kdu_instance = k8s["k8scluster-uuid"], k8s["kdu-instance"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004659 await self._on_update_k8s_db(
4660 cluster_uuid, kdu_instance, filter={"_id": nsr_id}, vca_id=vca_id
4661 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304662 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004663 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304664 table, filter = "nsrs", {"_id": nsr_id}
4665 path = "_admin.deployed.VCA.{}.".format(vca_index)
4666 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304667
4668 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4669 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4670
tierno59d22d22018-09-25 18:10:19 +02004671 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004672 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004673 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004674 if not task_is_locked_by_me:
4675 return
4676
tierno59d22d22018-09-25 18:10:19 +02004677 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4678 self.logger.debug(logging_text + "Enter")
4679 # get all needed from database
4680 db_nsr = None
4681 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004682 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004683 db_nslcmop_update = {}
4684 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004685 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004686 exc = None
4687 try:
kuused124bfe2019-06-18 12:09:24 +02004688 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004689 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004690 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004691
quilesj4cda56b2019-12-05 10:02:20 +00004692 self._write_ns_status(
4693 nsr_id=nsr_id,
4694 ns_state=None,
4695 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004696 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004697 )
4698
tierno59d22d22018-09-25 18:10:19 +02004699 step = "Getting information from database"
4700 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4701 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01004702 if db_nslcmop["operationParams"].get("primitive_params"):
4703 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
4704 db_nslcmop["operationParams"]["primitive_params"]
4705 )
tiernoda964822019-01-14 15:53:47 +00004706
tiernoe4f7e6c2018-11-27 14:55:30 +00004707 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004708 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004709 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004710 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004711 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004712 primitive = db_nslcmop["operationParams"]["primitive"]
4713 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004714 timeout_ns_action = db_nslcmop["operationParams"].get(
4715 "timeout_ns_action", self.timeout_primitive
4716 )
tierno59d22d22018-09-25 18:10:19 +02004717
tierno1b633412019-02-25 16:48:23 +00004718 if vnf_index:
4719 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004720 db_vnfr = self.db.get_one(
4721 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4722 )
Guillermo Calvino98a3bd12022-02-01 18:59:50 +01004723 if db_vnfr.get("kdur"):
4724 kdur_list = []
4725 for kdur in db_vnfr["kdur"]:
4726 if kdur.get("additionalParams"):
Pedro Escaleirab1679e42022-03-31 00:08:05 +01004727 kdur["additionalParams"] = json.loads(
4728 kdur["additionalParams"]
4729 )
Guillermo Calvino98a3bd12022-02-01 18:59:50 +01004730 kdur_list.append(kdur)
4731 db_vnfr["kdur"] = kdur_list
tierno1b633412019-02-25 16:48:23 +00004732 step = "Getting vnfd from database"
4733 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
4734 else:
tierno067e04a2020-03-31 12:53:13 +00004735 step = "Getting nsd from database"
4736 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00004737
David Garciac1fe90a2021-03-31 19:12:02 +02004738 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00004739 # for backward compatibility
4740 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
4741 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
4742 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
4743 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4744
tiernoda964822019-01-14 15:53:47 +00004745 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00004746 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00004747 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03004748 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01004749 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03004750 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00004751 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03004752 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00004753 else:
tiernoa278b842020-07-08 15:33:55 +00004754 descriptor_configuration = db_nsd.get("ns-configuration")
4755
garciadeblas5697b8b2021-03-24 09:17:02 +01004756 if descriptor_configuration and descriptor_configuration.get(
4757 "config-primitive"
4758 ):
tiernoa278b842020-07-08 15:33:55 +00004759 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00004760 if config_primitive["name"] == primitive:
4761 config_primitive_desc = config_primitive
4762 break
tiernoda964822019-01-14 15:53:47 +00004763
garciadeblas6bed6b32020-07-20 11:05:42 +00004764 if not config_primitive_desc:
4765 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004766 raise LcmException(
4767 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
4768 primitive
4769 )
4770 )
garciadeblas6bed6b32020-07-20 11:05:42 +00004771 primitive_name = primitive
4772 ee_descriptor_id = None
4773 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004774 primitive_name = config_primitive_desc.get(
4775 "execution-environment-primitive", primitive
4776 )
4777 ee_descriptor_id = config_primitive_desc.get(
4778 "execution-environment-ref"
4779 )
tierno1b633412019-02-25 16:48:23 +00004780
tierno1b633412019-02-25 16:48:23 +00004781 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00004782 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004783 vdur = next(
4784 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
4785 )
bravof922c4172020-11-24 21:21:43 -03004786 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004787 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01004788 kdur = next(
4789 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
4790 )
bravof922c4172020-11-24 21:21:43 -03004791 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004792 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004793 desc_params = parse_yaml_strings(
4794 db_vnfr.get("additionalParamsForVnf")
4795 )
tierno1b633412019-02-25 16:48:23 +00004796 else:
bravof922c4172020-11-24 21:21:43 -03004797 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03004798 if kdu_name and get_configuration(db_vnfd, kdu_name):
4799 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01004800 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01004801 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004802 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01004803 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004804 actions.add(primitive["name"])
4805 kdu_action = True if primitive_name in actions else False
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004806
tiernoda964822019-01-14 15:53:47 +00004807 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01004808 if kdu_name and (
4809 primitive_name in ("upgrade", "rollback", "status") or kdu_action
4810 ):
tierno067e04a2020-03-31 12:53:13 +00004811 # kdur and desc_params already set from before
4812 if primitive_params:
4813 desc_params.update(primitive_params)
4814 # TODO Check if we will need something at vnf level
4815 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004816 if (
4817 kdu_name == kdu["kdu-name"]
4818 and kdu["member-vnf-index"] == vnf_index
4819 ):
tierno067e04a2020-03-31 12:53:13 +00004820 break
4821 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004822 raise LcmException(
4823 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
4824 )
quilesj7e13aeb2019-10-08 13:34:55 +02004825
tierno067e04a2020-03-31 12:53:13 +00004826 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01004827 msg = "unknown k8scluster-type '{}'".format(
4828 kdu.get("k8scluster-type")
4829 )
tierno067e04a2020-03-31 12:53:13 +00004830 raise LcmException(msg)
4831
garciadeblas5697b8b2021-03-24 09:17:02 +01004832 db_dict = {
4833 "collection": "nsrs",
4834 "filter": {"_id": nsr_id},
4835 "path": "_admin.deployed.K8s.{}".format(index),
4836 }
4837 self.logger.debug(
4838 logging_text
4839 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
4840 )
tiernoa278b842020-07-08 15:33:55 +00004841 step = "Executing kdu {}".format(primitive_name)
4842 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00004843 if desc_params.get("kdu_model"):
4844 kdu_model = desc_params.get("kdu_model")
4845 del desc_params["kdu_model"]
4846 else:
4847 kdu_model = kdu.get("kdu-model")
4848 parts = kdu_model.split(sep=":")
4849 if len(parts) == 2:
4850 kdu_model = parts[0]
4851
4852 detailed_status = await asyncio.wait_for(
4853 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
4854 cluster_uuid=kdu.get("k8scluster-uuid"),
4855 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004856 atomic=True,
4857 kdu_model=kdu_model,
4858 params=desc_params,
4859 db_dict=db_dict,
4860 timeout=timeout_ns_action,
4861 ),
4862 timeout=timeout_ns_action + 10,
4863 )
4864 self.logger.debug(
4865 logging_text + " Upgrade of kdu {} done".format(detailed_status)
4866 )
tiernoa278b842020-07-08 15:33:55 +00004867 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00004868 detailed_status = await asyncio.wait_for(
4869 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
4870 cluster_uuid=kdu.get("k8scluster-uuid"),
4871 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004872 db_dict=db_dict,
4873 ),
4874 timeout=timeout_ns_action,
4875 )
tiernoa278b842020-07-08 15:33:55 +00004876 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00004877 detailed_status = await asyncio.wait_for(
4878 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
4879 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004880 kdu_instance=kdu.get("kdu-instance"),
4881 vca_id=vca_id,
4882 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004883 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004884 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004885 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004886 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
4887 kdu["kdu-name"], nsr_id
4888 )
4889 params = self._map_primitive_params(
4890 config_primitive_desc, primitive_params, desc_params
4891 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004892
4893 detailed_status = await asyncio.wait_for(
4894 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
4895 cluster_uuid=kdu.get("k8scluster-uuid"),
4896 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00004897 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004898 params=params,
4899 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02004900 timeout=timeout_ns_action,
4901 vca_id=vca_id,
4902 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004903 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004904 )
tierno067e04a2020-03-31 12:53:13 +00004905
4906 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004907 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00004908 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004909 detailed_status = ""
4910 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00004911 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004912 ee_id, vca_type = self._look_for_deployed_vca(
4913 nsr_deployed["VCA"],
4914 member_vnf_index=vnf_index,
4915 vdu_id=vdu_id,
4916 vdu_count_index=vdu_count_index,
4917 ee_descriptor_id=ee_descriptor_id,
4918 )
4919 for vca_index, vca_deployed in enumerate(
4920 db_nsr["_admin"]["deployed"]["VCA"]
4921 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05304922 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01004923 db_dict = {
4924 "collection": "nsrs",
4925 "filter": {"_id": nsr_id},
4926 "path": "_admin.deployed.VCA.{}.".format(vca_index),
4927 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05304928 break
garciadeblas5697b8b2021-03-24 09:17:02 +01004929 (
4930 nslcmop_operation_state,
4931 detailed_status,
4932 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00004933 ee_id,
tiernoa278b842020-07-08 15:33:55 +00004934 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004935 primitive_params=self._map_primitive_params(
4936 config_primitive_desc, primitive_params, desc_params
4937 ),
tierno588547c2020-07-01 15:30:20 +00004938 timeout=timeout_ns_action,
4939 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004940 db_dict=db_dict,
4941 vca_id=vca_id,
4942 )
tierno067e04a2020-03-31 12:53:13 +00004943
4944 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01004945 error_description_nslcmop = (
4946 detailed_status if nslcmop_operation_state == "FAILED" else ""
4947 )
4948 self.logger.debug(
4949 logging_text
4950 + " task Done with result {} {}".format(
4951 nslcmop_operation_state, detailed_status
4952 )
4953 )
tierno59d22d22018-09-25 18:10:19 +02004954 return # database update is called inside finally
4955
tiernof59ad6c2020-04-08 12:50:52 +00004956 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02004957 self.logger.error(logging_text + "Exit Exception {}".format(e))
4958 exc = e
4959 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004960 self.logger.error(
4961 logging_text + "Cancelled Exception while '{}'".format(step)
4962 )
tierno59d22d22018-09-25 18:10:19 +02004963 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00004964 except asyncio.TimeoutError:
4965 self.logger.error(logging_text + "Timeout while '{}'".format(step))
4966 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02004967 except Exception as e:
4968 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004969 self.logger.critical(
4970 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
4971 exc_info=True,
4972 )
tierno59d22d22018-09-25 18:10:19 +02004973 finally:
tierno067e04a2020-03-31 12:53:13 +00004974 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01004975 db_nslcmop_update[
4976 "detailed-status"
4977 ] = (
4978 detailed_status
4979 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00004980 nslcmop_operation_state = "FAILED"
4981 if db_nsr:
4982 self._write_ns_status(
4983 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004984 ns_state=db_nsr[
4985 "nsState"
4986 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00004987 current_operation="IDLE",
4988 current_operation_id=None,
4989 # error_description=error_description_nsr,
4990 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004991 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00004992 )
4993
garciadeblas5697b8b2021-03-24 09:17:02 +01004994 self._write_op_status(
4995 op_id=nslcmop_id,
4996 stage="",
4997 error_message=error_description_nslcmop,
4998 operation_state=nslcmop_operation_state,
4999 other_update=db_nslcmop_update,
5000 )
tierno067e04a2020-03-31 12:53:13 +00005001
tierno59d22d22018-09-25 18:10:19 +02005002 if nslcmop_operation_state:
5003 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005004 await self.msg.aiowrite(
5005 "ns",
5006 "actioned",
5007 {
5008 "nsr_id": nsr_id,
5009 "nslcmop_id": nslcmop_id,
5010 "operationState": nslcmop_operation_state,
5011 },
5012 loop=self.loop,
5013 )
tierno59d22d22018-09-25 18:10:19 +02005014 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01005015 self.logger.error(
5016 logging_text + "kafka_write notification Exception {}".format(e)
5017 )
tierno59d22d22018-09-25 18:10:19 +02005018 self.logger.debug(logging_text + "Exit")
5019 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00005020 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02005021
5022 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02005023 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01005024 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02005025 if not task_is_locked_by_me:
5026 return
5027
tierno59d22d22018-09-25 18:10:19 +02005028 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01005029 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03005030 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00005031 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02005032 self.logger.debug(logging_text + "Enter")
5033 # get all needed from database
5034 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02005035 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00005036 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02005037 exc = None
tierno9ab95942018-10-10 16:44:22 +02005038 # in case of error, indicates what part of scale was failed to put nsr at error status
5039 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02005040 old_operational_status = ""
5041 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03005042 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02005043 try:
kuused124bfe2019-06-18 12:09:24 +02005044 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00005045 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01005046 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
5047 self._write_ns_status(
5048 nsr_id=nsr_id,
5049 ns_state=None,
5050 current_operation="SCALING",
5051 current_operation_id=nslcmop_id,
5052 )
quilesj4cda56b2019-12-05 10:02:20 +00005053
ikalyvas02d9e7b2019-05-27 18:16:01 +03005054 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005055 self.logger.debug(
5056 step + " after having waited for previous tasks to be completed"
5057 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005058 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03005059
ikalyvas02d9e7b2019-05-27 18:16:01 +03005060 step = "Getting nsr from database"
5061 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005062 old_operational_status = db_nsr["operational-status"]
5063 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03005064
tierno59d22d22018-09-25 18:10:19 +02005065 step = "Parsing scaling parameters"
5066 db_nsr_update["operational-status"] = "scaling"
5067 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00005068 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01005069
garciadeblas5697b8b2021-03-24 09:17:02 +01005070 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
5071 "scaleByStepData"
5072 ]["member-vnf-index"]
5073 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
5074 "scaleByStepData"
5075 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02005076 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00005077 # for backward compatibility
5078 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5079 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5080 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5081 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5082
tierno59d22d22018-09-25 18:10:19 +02005083 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005084 db_vnfr = self.db.get_one(
5085 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5086 )
bravof922c4172020-11-24 21:21:43 -03005087
David Garciac1fe90a2021-03-31 19:12:02 +02005088 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5089
tierno59d22d22018-09-25 18:10:19 +02005090 step = "Getting vnfd from database"
5091 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005092
aktas13251562021-02-12 22:19:10 +03005093 base_folder = db_vnfd["_admin"]["storage"]
5094
tierno59d22d22018-09-25 18:10:19 +02005095 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03005096 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01005097 get_scaling_aspect(db_vnfd),
5098 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03005099 )
5100 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01005101 raise LcmException(
5102 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
5103 "at vnfd:scaling-group-descriptor".format(scaling_group)
5104 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005105
tierno15b1cf12019-08-29 13:21:40 +00005106 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03005107 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02005108 nb_scale_op = 0
5109 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005110 self.update_db_2(
5111 "nsrs",
5112 nsr_id,
5113 {
5114 "_admin.scaling-group": [
5115 {"name": scaling_group, "nb-scale-op": 0}
5116 ]
5117 },
5118 )
tierno59d22d22018-09-25 18:10:19 +02005119 admin_scale_index = 0
5120 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005121 for admin_scale_index, admin_scale_info in enumerate(
5122 db_nsr["_admin"]["scaling-group"]
5123 ):
tierno59d22d22018-09-25 18:10:19 +02005124 if admin_scale_info["name"] == scaling_group:
5125 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
5126 break
tierno9ab95942018-10-10 16:44:22 +02005127 else: # not found, set index one plus last element and add new entry with the name
5128 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01005129 db_nsr_update[
5130 "_admin.scaling-group.{}.name".format(admin_scale_index)
5131 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03005132
5133 vca_scaling_info = []
5134 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02005135 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03005136 if "aspect-delta-details" not in scaling_descriptor:
5137 raise LcmException(
5138 "Aspect delta details not fount in scaling descriptor {}".format(
5139 scaling_descriptor["name"]
5140 )
5141 )
tierno59d22d22018-09-25 18:10:19 +02005142 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03005143 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02005144
aktas5f75f102021-03-15 11:26:10 +03005145 scaling_info["scaling_direction"] = "OUT"
5146 scaling_info["vdu-create"] = {}
5147 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03005148 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005149 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03005150 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005151 # vdu_index also provides the number of instance of the targeted vdu
5152 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01005153 cloud_init_text = self._get_vdu_cloud_init_content(
5154 vdud, db_vnfd
5155 )
tierno72ef84f2020-10-06 08:22:07 +00005156 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01005157 additional_params = (
5158 self._get_vdu_additional_params(db_vnfr, vdud["id"])
5159 or {}
5160 )
bravof832f8992020-12-07 12:57:31 -03005161 cloud_init_list = []
5162
5163 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5164 max_instance_count = 10
5165 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01005166 max_instance_count = vdu_profile.get(
5167 "max-number-of-instances", 10
5168 )
5169
5170 default_instance_num = get_number_of_instances(
5171 db_vnfd, vdud["id"]
5172 )
aktas5f75f102021-03-15 11:26:10 +03005173 instances_number = vdu_delta.get("number-of-instances", 1)
5174 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03005175
aktas5f75f102021-03-15 11:26:10 +03005176 new_instance_count = nb_scale_op + default_instance_num
5177 # Control if new count is over max and vdu count is less than max.
5178 # Then assign new instance count
5179 if new_instance_count > max_instance_count > vdu_count:
5180 instances_number = new_instance_count - max_instance_count
5181 else:
5182 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03005183
aktas5f75f102021-03-15 11:26:10 +03005184 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03005185 raise LcmException(
5186 "reached the limit of {} (max-instance-count) "
5187 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005188 "scaling-group-descriptor '{}'".format(
5189 nb_scale_op, scaling_group
5190 )
bravof922c4172020-11-24 21:21:43 -03005191 )
bravof832f8992020-12-07 12:57:31 -03005192 for x in range(vdu_delta.get("number-of-instances", 1)):
5193 if cloud_init_text:
5194 # TODO Information of its own ip is not available because db_vnfr is not updated.
5195 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01005196 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03005197 )
bravof832f8992020-12-07 12:57:31 -03005198 cloud_init_list.append(
5199 self._parse_cloud_init(
5200 cloud_init_text,
5201 additional_params,
5202 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01005203 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03005204 )
5205 )
aktas5f75f102021-03-15 11:26:10 +03005206 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005207 {
5208 "osm_vdu_id": vdu_delta["id"],
5209 "member-vnf-index": vnf_index,
5210 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01005211 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03005212 }
5213 )
aktas5f75f102021-03-15 11:26:10 +03005214 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
5215 for kdu_delta in delta.get("kdu-resource-delta", {}):
5216 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5217 kdu_name = kdu_profile["kdu-name"]
5218 resource_name = kdu_profile["resource-name"]
5219
5220 # Might have different kdus in the same delta
5221 # Should have list for each kdu
5222 if not scaling_info["kdu-create"].get(kdu_name, None):
5223 scaling_info["kdu-create"][kdu_name] = []
5224
5225 kdur = get_kdur(db_vnfr, kdu_name)
5226 if kdur.get("helm-chart"):
5227 k8s_cluster_type = "helm-chart-v3"
5228 self.logger.debug("kdur: {}".format(kdur))
5229 if (
5230 kdur.get("helm-version")
5231 and kdur.get("helm-version") == "v2"
5232 ):
5233 k8s_cluster_type = "helm-chart"
5234 raise NotImplementedError
5235 elif kdur.get("juju-bundle"):
5236 k8s_cluster_type = "juju-bundle"
5237 else:
5238 raise LcmException(
5239 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5240 "juju-bundle. Maybe an old NBI version is running".format(
5241 db_vnfr["member-vnf-index-ref"], kdu_name
5242 )
5243 )
5244
5245 max_instance_count = 10
5246 if kdu_profile and "max-number-of-instances" in kdu_profile:
5247 max_instance_count = kdu_profile.get(
5248 "max-number-of-instances", 10
5249 )
5250
5251 nb_scale_op += kdu_delta.get("number-of-instances", 1)
5252 deployed_kdu, _ = get_deployed_kdu(
5253 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03005254 )
aktas5f75f102021-03-15 11:26:10 +03005255 if deployed_kdu is None:
5256 raise LcmException(
5257 "KDU '{}' for vnf '{}' not deployed".format(
5258 kdu_name, vnf_index
5259 )
5260 )
5261 kdu_instance = deployed_kdu.get("kdu-instance")
5262 instance_num = await self.k8scluster_map[
5263 k8s_cluster_type
5264 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5265 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005266 "number-of-instances", 1
5267 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005268
aktas5f75f102021-03-15 11:26:10 +03005269 # Control if new count is over max and instance_num is less than max.
5270 # Then assign max instance number to kdu replica count
5271 if kdu_replica_count > max_instance_count > instance_num:
5272 kdu_replica_count = max_instance_count
5273 if kdu_replica_count > max_instance_count:
5274 raise LcmException(
5275 "reached the limit of {} (max-instance-count) "
5276 "scaling-out operations for the "
5277 "scaling-group-descriptor '{}'".format(
5278 instance_num, scaling_group
5279 )
5280 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005281
aktas5f75f102021-03-15 11:26:10 +03005282 for x in range(kdu_delta.get("number-of-instances", 1)):
5283 vca_scaling_info.append(
5284 {
5285 "osm_kdu_id": kdu_name,
5286 "member-vnf-index": vnf_index,
5287 "type": "create",
5288 "kdu_index": instance_num + x - 1,
5289 }
5290 )
5291 scaling_info["kdu-create"][kdu_name].append(
5292 {
5293 "member-vnf-index": vnf_index,
5294 "type": "create",
5295 "k8s-cluster-type": k8s_cluster_type,
5296 "resource-name": resource_name,
5297 "scale": kdu_replica_count,
5298 }
5299 )
5300 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03005301 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03005302
5303 scaling_info["scaling_direction"] = "IN"
5304 scaling_info["vdu-delete"] = {}
5305 scaling_info["kdu-delete"] = {}
5306
bravof832f8992020-12-07 12:57:31 -03005307 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005308 for vdu_delta in delta.get("vdu-delta", {}):
5309 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03005310 min_instance_count = 0
5311 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5312 if vdu_profile and "min-number-of-instances" in vdu_profile:
5313 min_instance_count = vdu_profile["min-number-of-instances"]
5314
garciadeblas5697b8b2021-03-24 09:17:02 +01005315 default_instance_num = get_number_of_instances(
5316 db_vnfd, vdu_delta["id"]
5317 )
aktas5f75f102021-03-15 11:26:10 +03005318 instance_num = vdu_delta.get("number-of-instances", 1)
5319 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03005320
aktas5f75f102021-03-15 11:26:10 +03005321 new_instance_count = nb_scale_op + default_instance_num
5322
5323 if new_instance_count < min_instance_count < vdu_count:
5324 instances_number = min_instance_count - new_instance_count
5325 else:
5326 instances_number = instance_num
5327
5328 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03005329 raise LcmException(
5330 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005331 "scaling-group-descriptor '{}'".format(
5332 nb_scale_op, scaling_group
5333 )
bravof832f8992020-12-07 12:57:31 -03005334 )
aktas13251562021-02-12 22:19:10 +03005335 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03005336 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005337 {
5338 "osm_vdu_id": vdu_delta["id"],
5339 "member-vnf-index": vnf_index,
5340 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01005341 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03005342 }
5343 )
aktas5f75f102021-03-15 11:26:10 +03005344 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
5345 for kdu_delta in delta.get("kdu-resource-delta", {}):
5346 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5347 kdu_name = kdu_profile["kdu-name"]
5348 resource_name = kdu_profile["resource-name"]
5349
5350 if not scaling_info["kdu-delete"].get(kdu_name, None):
5351 scaling_info["kdu-delete"][kdu_name] = []
5352
5353 kdur = get_kdur(db_vnfr, kdu_name)
5354 if kdur.get("helm-chart"):
5355 k8s_cluster_type = "helm-chart-v3"
5356 self.logger.debug("kdur: {}".format(kdur))
5357 if (
5358 kdur.get("helm-version")
5359 and kdur.get("helm-version") == "v2"
5360 ):
5361 k8s_cluster_type = "helm-chart"
5362 raise NotImplementedError
5363 elif kdur.get("juju-bundle"):
5364 k8s_cluster_type = "juju-bundle"
5365 else:
5366 raise LcmException(
5367 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5368 "juju-bundle. Maybe an old NBI version is running".format(
5369 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
5370 )
5371 )
5372
5373 min_instance_count = 0
5374 if kdu_profile and "min-number-of-instances" in kdu_profile:
5375 min_instance_count = kdu_profile["min-number-of-instances"]
5376
5377 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
5378 deployed_kdu, _ = get_deployed_kdu(
5379 nsr_deployed, kdu_name, vnf_index
5380 )
5381 if deployed_kdu is None:
5382 raise LcmException(
5383 "KDU '{}' for vnf '{}' not deployed".format(
5384 kdu_name, vnf_index
5385 )
5386 )
5387 kdu_instance = deployed_kdu.get("kdu-instance")
5388 instance_num = await self.k8scluster_map[
5389 k8s_cluster_type
5390 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5391 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005392 "number-of-instances", 1
5393 )
tierno59d22d22018-09-25 18:10:19 +02005394
aktas5f75f102021-03-15 11:26:10 +03005395 if kdu_replica_count < min_instance_count < instance_num:
5396 kdu_replica_count = min_instance_count
5397 if kdu_replica_count < min_instance_count:
5398 raise LcmException(
5399 "reached the limit of {} (min-instance-count) scaling-in operations for the "
5400 "scaling-group-descriptor '{}'".format(
5401 instance_num, scaling_group
5402 )
5403 )
5404
5405 for x in range(kdu_delta.get("number-of-instances", 1)):
5406 vca_scaling_info.append(
5407 {
5408 "osm_kdu_id": kdu_name,
5409 "member-vnf-index": vnf_index,
5410 "type": "delete",
5411 "kdu_index": instance_num - x - 1,
5412 }
5413 )
5414 scaling_info["kdu-delete"][kdu_name].append(
5415 {
5416 "member-vnf-index": vnf_index,
5417 "type": "delete",
5418 "k8s-cluster-type": k8s_cluster_type,
5419 "resource-name": resource_name,
5420 "scale": kdu_replica_count,
5421 }
5422 )
5423
tierno59d22d22018-09-25 18:10:19 +02005424 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03005425 vdu_delete = copy(scaling_info.get("vdu-delete"))
5426 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02005427 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02005428 if vdu_delete.get(vdur["vdu-id-ref"]):
5429 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03005430 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005431 {
5432 "name": vdur.get("name") or vdur.get("vdu-name"),
5433 "vdu_id": vdur["vdu-id-ref"],
5434 "interface": [],
5435 }
5436 )
tierno59d22d22018-09-25 18:10:19 +02005437 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03005438 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005439 {
5440 "name": interface["name"],
5441 "ip_address": interface["ip-address"],
5442 "mac_address": interface.get("mac-address"),
5443 }
5444 )
tierno2357f4e2020-10-19 16:38:59 +00005445 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02005446
kuuseac3a8882019-10-03 10:48:06 +02005447 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005448 step = "Executing pre-scale vnf-config-primitive"
5449 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005450 for scaling_config_action in scaling_descriptor[
5451 "scaling-config-action"
5452 ]:
5453 if (
5454 scaling_config_action.get("trigger") == "pre-scale-in"
5455 and scaling_type == "SCALE_IN"
5456 ) or (
5457 scaling_config_action.get("trigger") == "pre-scale-out"
5458 and scaling_type == "SCALE_OUT"
5459 ):
5460 vnf_config_primitive = scaling_config_action[
5461 "vnf-config-primitive-name-ref"
5462 ]
5463 step = db_nslcmop_update[
5464 "detailed-status"
5465 ] = "executing pre-scale scaling-config-action '{}'".format(
5466 vnf_config_primitive
5467 )
tiernoda964822019-01-14 15:53:47 +00005468
tierno59d22d22018-09-25 18:10:19 +02005469 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005470 for config_primitive in (
5471 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5472 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005473 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005474 break
5475 else:
5476 raise LcmException(
5477 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00005478 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01005479 "primitive".format(scaling_group, vnf_config_primitive)
5480 )
tiernoda964822019-01-14 15:53:47 +00005481
aktas5f75f102021-03-15 11:26:10 +03005482 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005483 if db_vnfr.get("additionalParamsForVnf"):
5484 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02005485
tierno9ab95942018-10-10 16:44:22 +02005486 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005487 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005488 primitive_params = self._map_primitive_params(
5489 config_primitive, {}, vnfr_params
5490 )
kuuseac3a8882019-10-03 10:48:06 +02005491
tierno7c4e24c2020-05-13 08:41:35 +00005492 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005493 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005494 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005495 vnf_index,
5496 vnf_config_primitive,
5497 primitive_params,
5498 "PRE-SCALE",
5499 )
tierno7c4e24c2020-05-13 08:41:35 +00005500 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005501 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005502 result = "COMPLETED"
5503 result_detail = "Done"
5504 self.logger.debug(
5505 logging_text
5506 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5507 vnf_config_primitive, result, result_detail
5508 )
5509 )
kuuseac3a8882019-10-03 10:48:06 +02005510 else:
tierno7c4e24c2020-05-13 08:41:35 +00005511 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005512 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005513 op_index = (
5514 len(db_nslcmop.get("_admin", {}).get("operations"))
5515 - 1
5516 )
5517 self.logger.debug(
5518 logging_text
5519 + "vnf_config_primitive={} New sub-operation".format(
5520 vnf_config_primitive
5521 )
5522 )
kuuseac3a8882019-10-03 10:48:06 +02005523 else:
tierno7c4e24c2020-05-13 08:41:35 +00005524 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005525 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5526 op_index
5527 ]
5528 vnf_index = op.get("member_vnf_index")
5529 vnf_config_primitive = op.get("primitive")
5530 primitive_params = op.get("primitive_params")
5531 self.logger.debug(
5532 logging_text
5533 + "vnf_config_primitive={} Sub-operation retry".format(
5534 vnf_config_primitive
5535 )
5536 )
tierno588547c2020-07-01 15:30:20 +00005537 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005538 ee_descriptor_id = config_primitive.get(
5539 "execution-environment-ref"
5540 )
5541 primitive_name = config_primitive.get(
5542 "execution-environment-primitive", vnf_config_primitive
5543 )
5544 ee_id, vca_type = self._look_for_deployed_vca(
5545 nsr_deployed["VCA"],
5546 member_vnf_index=vnf_index,
5547 vdu_id=None,
5548 vdu_count_index=None,
5549 ee_descriptor_id=ee_descriptor_id,
5550 )
kuuseac3a8882019-10-03 10:48:06 +02005551 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01005552 ee_id,
5553 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02005554 primitive_params,
5555 vca_type=vca_type,
5556 vca_id=vca_id,
5557 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005558 self.logger.debug(
5559 logging_text
5560 + "vnf_config_primitive={} Done with result {} {}".format(
5561 vnf_config_primitive, result, result_detail
5562 )
5563 )
kuuseac3a8882019-10-03 10:48:06 +02005564 # Update operationState = COMPLETED | FAILED
5565 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005566 db_nslcmop, op_index, result, result_detail
5567 )
kuuseac3a8882019-10-03 10:48:06 +02005568
tierno59d22d22018-09-25 18:10:19 +02005569 if result == "FAILED":
5570 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005571 db_nsr_update["config-status"] = old_config_status
5572 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005573 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005574
garciadeblas5697b8b2021-03-24 09:17:02 +01005575 db_nsr_update[
5576 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
5577 ] = nb_scale_op
5578 db_nsr_update[
5579 "_admin.scaling-group.{}.time".format(admin_scale_index)
5580 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00005581
aktas13251562021-02-12 22:19:10 +03005582 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005583 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005584 step = db_nslcmop_update[
5585 "detailed-status"
5586 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03005587 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005588 for vca_info in vca_scaling_info:
5589 if vca_info["type"] == "delete":
5590 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005591 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005592 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005593 )
aktas5f75f102021-03-15 11:26:10 +03005594 if vca_info.get("osm_vdu_id"):
5595 vdu_id = vca_info["osm_vdu_id"]
5596 vdu_index = int(vca_info["vdu_index"])
5597 stage[
5598 1
5599 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5600 member_vnf_index, vdu_id, vdu_index
5601 )
5602 else:
5603 vdu_index = 0
5604 kdu_id = vca_info["osm_kdu_id"]
5605 stage[
5606 1
5607 ] = "Scaling member_vnf_index={}, kdu_id={}, vdu_index={} ".format(
5608 member_vnf_index, kdu_id, vdu_index
5609 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005610 stage[2] = step = "Scaling in VCA"
5611 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03005612 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
5613 config_update = db_nsr["configurationStatus"]
5614 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01005615 if (
5616 (vca or vca.get("ee_id"))
5617 and vca["member-vnf-index"] == member_vnf_index
5618 and vca["vdu_count_index"] == vdu_index
5619 ):
aktas13251562021-02-12 22:19:10 +03005620 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005621 config_descriptor = get_configuration(
5622 db_vnfd, vca.get("vdu_id")
5623 )
aktas13251562021-02-12 22:19:10 +03005624 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005625 config_descriptor = get_configuration(
5626 db_vnfd, vca.get("kdu_name")
5627 )
aktas13251562021-02-12 22:19:10 +03005628 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005629 config_descriptor = get_configuration(
5630 db_vnfd, db_vnfd["id"]
5631 )
5632 operation_params = (
5633 db_nslcmop.get("operationParams") or {}
5634 )
5635 exec_terminate_primitives = not operation_params.get(
5636 "skip_terminate_primitives"
5637 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02005638 task = asyncio.ensure_future(
5639 asyncio.wait_for(
5640 self.destroy_N2VC(
5641 logging_text,
5642 db_nslcmop,
5643 vca,
5644 config_descriptor,
5645 vca_index,
5646 destroy_ee=True,
5647 exec_primitives=exec_terminate_primitives,
5648 scaling_in=True,
5649 vca_id=vca_id,
5650 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005651 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02005652 )
5653 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005654 tasks_dict_info[task] = "Terminating VCA {}".format(
5655 vca.get("ee_id")
5656 )
aktas13251562021-02-12 22:19:10 +03005657 del vca_update[vca_index]
5658 del config_update[vca_index]
5659 # wait for pending tasks of terminate primitives
5660 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005661 self.logger.debug(
5662 logging_text
5663 + "Waiting for tasks {}".format(
5664 list(tasks_dict_info.keys())
5665 )
5666 )
5667 error_list = await self._wait_for_tasks(
5668 logging_text,
5669 tasks_dict_info,
5670 min(
5671 self.timeout_charm_delete, self.timeout_ns_terminate
5672 ),
5673 stage,
5674 nslcmop_id,
5675 )
aktas13251562021-02-12 22:19:10 +03005676 tasks_dict_info.clear()
5677 if error_list:
5678 raise LcmException("; ".join(error_list))
5679
5680 db_vca_and_config_update = {
5681 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01005682 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03005683 }
garciadeblas5697b8b2021-03-24 09:17:02 +01005684 self.update_db_2(
5685 "nsrs", db_nsr["_id"], db_vca_and_config_update
5686 )
aktas13251562021-02-12 22:19:10 +03005687 scale_process = None
5688 # SCALE-IN VCA - END
5689
kuuseac3a8882019-10-03 10:48:06 +02005690 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005691 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02005692 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00005693 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005694 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03005695 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01005696 )
aktas5f75f102021-03-15 11:26:10 +03005697 scaling_info.pop("vdu-create", None)
5698 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02005699
tierno9ab95942018-10-10 16:44:22 +02005700 scale_process = None
aktas13251562021-02-12 22:19:10 +03005701 # SCALE RO - END
5702
aktas5f75f102021-03-15 11:26:10 +03005703 # SCALE KDU - BEGIN
5704 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
5705 scale_process = "KDU"
5706 await self._scale_kdu(
5707 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
5708 )
5709 scaling_info.pop("kdu-create", None)
5710 scaling_info.pop("kdu-delete", None)
5711
5712 scale_process = None
5713 # SCALE KDU - END
5714
5715 if db_nsr_update:
5716 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5717
aktas13251562021-02-12 22:19:10 +03005718 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005719 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005720 step = db_nslcmop_update[
5721 "detailed-status"
5722 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03005723 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005724 for vca_info in vca_scaling_info:
5725 if vca_info["type"] == "create":
5726 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005727 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005728 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005729 )
aktas13251562021-02-12 22:19:10 +03005730 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03005731 if vca_info.get("osm_vdu_id"):
5732 vdu_index = int(vca_info["vdu_index"])
5733 deploy_params = {"OSM": get_osm_params(db_vnfr)}
5734 if db_vnfr.get("additionalParamsForVnf"):
5735 deploy_params.update(
5736 parse_yaml_strings(
5737 db_vnfr["additionalParamsForVnf"].copy()
5738 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005739 )
aktas5f75f102021-03-15 11:26:10 +03005740 descriptor_config = get_configuration(
5741 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005742 )
aktas5f75f102021-03-15 11:26:10 +03005743 if descriptor_config:
5744 vdu_id = None
5745 vdu_name = None
5746 kdu_name = None
5747 self._deploy_n2vc(
5748 logging_text=logging_text
5749 + "member_vnf_index={} ".format(member_vnf_index),
5750 db_nsr=db_nsr,
5751 db_vnfr=db_vnfr,
5752 nslcmop_id=nslcmop_id,
5753 nsr_id=nsr_id,
5754 nsi_id=nsi_id,
5755 vnfd_id=vnfd_id,
5756 vdu_id=vdu_id,
5757 kdu_name=kdu_name,
5758 member_vnf_index=member_vnf_index,
5759 vdu_index=vdu_index,
5760 vdu_name=vdu_name,
5761 deploy_params=deploy_params,
5762 descriptor_config=descriptor_config,
5763 base_folder=base_folder,
5764 task_instantiation_info=tasks_dict_info,
5765 stage=stage,
5766 )
5767 vdu_id = vca_info["osm_vdu_id"]
5768 vdur = find_in_list(
5769 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03005770 )
aktas5f75f102021-03-15 11:26:10 +03005771 descriptor_config = get_configuration(db_vnfd, vdu_id)
5772 if vdur.get("additionalParams"):
5773 deploy_params_vdu = parse_yaml_strings(
5774 vdur["additionalParams"]
5775 )
5776 else:
5777 deploy_params_vdu = deploy_params
5778 deploy_params_vdu["OSM"] = get_osm_params(
5779 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01005780 )
aktas5f75f102021-03-15 11:26:10 +03005781 if descriptor_config:
5782 vdu_name = None
5783 kdu_name = None
5784 stage[
5785 1
5786 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005787 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03005788 )
5789 stage[2] = step = "Scaling out VCA"
5790 self._write_op_status(op_id=nslcmop_id, stage=stage)
5791 self._deploy_n2vc(
5792 logging_text=logging_text
5793 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5794 member_vnf_index, vdu_id, vdu_index
5795 ),
5796 db_nsr=db_nsr,
5797 db_vnfr=db_vnfr,
5798 nslcmop_id=nslcmop_id,
5799 nsr_id=nsr_id,
5800 nsi_id=nsi_id,
5801 vnfd_id=vnfd_id,
5802 vdu_id=vdu_id,
5803 kdu_name=kdu_name,
5804 member_vnf_index=member_vnf_index,
5805 vdu_index=vdu_index,
5806 vdu_name=vdu_name,
5807 deploy_params=deploy_params_vdu,
5808 descriptor_config=descriptor_config,
5809 base_folder=base_folder,
5810 task_instantiation_info=tasks_dict_info,
5811 stage=stage,
5812 )
5813 else:
5814 kdu_name = vca_info["osm_kdu_id"]
5815 descriptor_config = get_configuration(db_vnfd, kdu_name)
5816 if descriptor_config:
5817 vdu_id = None
5818 kdu_index = int(vca_info["kdu_index"])
5819 vdu_name = None
5820 kdur = next(
5821 x
5822 for x in db_vnfr["kdur"]
5823 if x["kdu-name"] == kdu_name
5824 )
5825 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
5826 if kdur.get("additionalParams"):
5827 deploy_params_kdu = parse_yaml_strings(
5828 kdur["additionalParams"]
5829 )
5830
5831 self._deploy_n2vc(
5832 logging_text=logging_text,
5833 db_nsr=db_nsr,
5834 db_vnfr=db_vnfr,
5835 nslcmop_id=nslcmop_id,
5836 nsr_id=nsr_id,
5837 nsi_id=nsi_id,
5838 vnfd_id=vnfd_id,
5839 vdu_id=vdu_id,
5840 kdu_name=kdu_name,
5841 member_vnf_index=member_vnf_index,
5842 vdu_index=kdu_index,
5843 vdu_name=vdu_name,
5844 deploy_params=deploy_params_kdu,
5845 descriptor_config=descriptor_config,
5846 base_folder=base_folder,
5847 task_instantiation_info=tasks_dict_info,
5848 stage=stage,
5849 )
aktas13251562021-02-12 22:19:10 +03005850 # SCALE-UP VCA - END
5851 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02005852
kuuseac3a8882019-10-03 10:48:06 +02005853 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005854 # execute primitive service POST-SCALING
5855 step = "Executing post-scale vnf-config-primitive"
5856 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005857 for scaling_config_action in scaling_descriptor[
5858 "scaling-config-action"
5859 ]:
5860 if (
5861 scaling_config_action.get("trigger") == "post-scale-in"
5862 and scaling_type == "SCALE_IN"
5863 ) or (
5864 scaling_config_action.get("trigger") == "post-scale-out"
5865 and scaling_type == "SCALE_OUT"
5866 ):
5867 vnf_config_primitive = scaling_config_action[
5868 "vnf-config-primitive-name-ref"
5869 ]
5870 step = db_nslcmop_update[
5871 "detailed-status"
5872 ] = "executing post-scale scaling-config-action '{}'".format(
5873 vnf_config_primitive
5874 )
tiernoda964822019-01-14 15:53:47 +00005875
aktas5f75f102021-03-15 11:26:10 +03005876 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005877 if db_vnfr.get("additionalParamsForVnf"):
5878 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
5879
tierno59d22d22018-09-25 18:10:19 +02005880 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03005881 for config_primitive in (
5882 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5883 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005884 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005885 break
5886 else:
tiernoa278b842020-07-08 15:33:55 +00005887 raise LcmException(
5888 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
5889 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01005890 "config-primitive".format(
5891 scaling_group, vnf_config_primitive
5892 )
5893 )
tierno9ab95942018-10-10 16:44:22 +02005894 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005895 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005896 primitive_params = self._map_primitive_params(
5897 config_primitive, {}, vnfr_params
5898 )
tiernod6de1992018-10-11 13:05:52 +02005899
tierno7c4e24c2020-05-13 08:41:35 +00005900 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005901 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005902 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005903 vnf_index,
5904 vnf_config_primitive,
5905 primitive_params,
5906 "POST-SCALE",
5907 )
quilesj4cda56b2019-12-05 10:02:20 +00005908 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005909 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005910 result = "COMPLETED"
5911 result_detail = "Done"
5912 self.logger.debug(
5913 logging_text
5914 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5915 vnf_config_primitive, result, result_detail
5916 )
5917 )
kuuseac3a8882019-10-03 10:48:06 +02005918 else:
quilesj4cda56b2019-12-05 10:02:20 +00005919 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005920 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005921 op_index = (
5922 len(db_nslcmop.get("_admin", {}).get("operations"))
5923 - 1
5924 )
5925 self.logger.debug(
5926 logging_text
5927 + "vnf_config_primitive={} New sub-operation".format(
5928 vnf_config_primitive
5929 )
5930 )
kuuseac3a8882019-10-03 10:48:06 +02005931 else:
tierno7c4e24c2020-05-13 08:41:35 +00005932 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005933 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5934 op_index
5935 ]
5936 vnf_index = op.get("member_vnf_index")
5937 vnf_config_primitive = op.get("primitive")
5938 primitive_params = op.get("primitive_params")
5939 self.logger.debug(
5940 logging_text
5941 + "vnf_config_primitive={} Sub-operation retry".format(
5942 vnf_config_primitive
5943 )
5944 )
tierno588547c2020-07-01 15:30:20 +00005945 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005946 ee_descriptor_id = config_primitive.get(
5947 "execution-environment-ref"
5948 )
5949 primitive_name = config_primitive.get(
5950 "execution-environment-primitive", vnf_config_primitive
5951 )
5952 ee_id, vca_type = self._look_for_deployed_vca(
5953 nsr_deployed["VCA"],
5954 member_vnf_index=vnf_index,
5955 vdu_id=None,
5956 vdu_count_index=None,
5957 ee_descriptor_id=ee_descriptor_id,
5958 )
kuuseac3a8882019-10-03 10:48:06 +02005959 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02005960 ee_id,
5961 primitive_name,
5962 primitive_params,
5963 vca_type=vca_type,
5964 vca_id=vca_id,
5965 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005966 self.logger.debug(
5967 logging_text
5968 + "vnf_config_primitive={} Done with result {} {}".format(
5969 vnf_config_primitive, result, result_detail
5970 )
5971 )
kuuseac3a8882019-10-03 10:48:06 +02005972 # Update operationState = COMPLETED | FAILED
5973 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005974 db_nslcmop, op_index, result, result_detail
5975 )
kuuseac3a8882019-10-03 10:48:06 +02005976
tierno59d22d22018-09-25 18:10:19 +02005977 if result == "FAILED":
5978 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005979 db_nsr_update["config-status"] = old_config_status
5980 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005981 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005982
garciadeblas5697b8b2021-03-24 09:17:02 +01005983 db_nsr_update[
5984 "detailed-status"
5985 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
5986 db_nsr_update["operational-status"] = (
5987 "running"
5988 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03005989 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005990 )
tiernod6de1992018-10-11 13:05:52 +02005991 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02005992 return
garciadeblas5697b8b2021-03-24 09:17:02 +01005993 except (
5994 ROclient.ROClientException,
5995 DbException,
5996 LcmException,
5997 NgRoException,
5998 ) as e:
tierno59d22d22018-09-25 18:10:19 +02005999 self.logger.error(logging_text + "Exit Exception {}".format(e))
6000 exc = e
6001 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01006002 self.logger.error(
6003 logging_text + "Cancelled Exception while '{}'".format(step)
6004 )
tierno59d22d22018-09-25 18:10:19 +02006005 exc = "Operation was cancelled"
6006 except Exception as e:
6007 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01006008 self.logger.critical(
6009 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
6010 exc_info=True,
6011 )
tierno59d22d22018-09-25 18:10:19 +02006012 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01006013 self._write_ns_status(
6014 nsr_id=nsr_id,
6015 ns_state=None,
6016 current_operation="IDLE",
6017 current_operation_id=None,
6018 )
aktas13251562021-02-12 22:19:10 +03006019 if tasks_dict_info:
6020 stage[1] = "Waiting for instantiate pending tasks."
6021 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01006022 exc = await self._wait_for_tasks(
6023 logging_text,
6024 tasks_dict_info,
6025 self.timeout_ns_deploy,
6026 stage,
6027 nslcmop_id,
6028 nsr_id=nsr_id,
6029 )
tierno59d22d22018-09-25 18:10:19 +02006030 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01006031 db_nslcmop_update[
6032 "detailed-status"
6033 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00006034 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02006035 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02006036 db_nsr_update["operational-status"] = old_operational_status
6037 db_nsr_update["config-status"] = old_config_status
6038 db_nsr_update["detailed-status"] = ""
6039 if scale_process:
6040 if "VCA" in scale_process:
6041 db_nsr_update["config-status"] = "failed"
6042 if "RO" in scale_process:
6043 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01006044 db_nsr_update[
6045 "detailed-status"
6046 ] = "FAILED scaling nslcmop={} {}: {}".format(
6047 nslcmop_id, step, exc
6048 )
tiernoa17d4f42020-04-28 09:59:23 +00006049 else:
6050 error_description_nslcmop = None
6051 nslcmop_operation_state = "COMPLETED"
6052 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00006053
garciadeblas5697b8b2021-03-24 09:17:02 +01006054 self._write_op_status(
6055 op_id=nslcmop_id,
6056 stage="",
6057 error_message=error_description_nslcmop,
6058 operation_state=nslcmop_operation_state,
6059 other_update=db_nslcmop_update,
6060 )
tiernoa17d4f42020-04-28 09:59:23 +00006061 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01006062 self._write_ns_status(
6063 nsr_id=nsr_id,
6064 ns_state=None,
6065 current_operation="IDLE",
6066 current_operation_id=None,
6067 other_update=db_nsr_update,
6068 )
tiernoa17d4f42020-04-28 09:59:23 +00006069
tierno59d22d22018-09-25 18:10:19 +02006070 if nslcmop_operation_state:
6071 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01006072 msg = {
6073 "nsr_id": nsr_id,
6074 "nslcmop_id": nslcmop_id,
6075 "operationState": nslcmop_operation_state,
6076 }
bravof922c4172020-11-24 21:21:43 -03006077 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02006078 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01006079 self.logger.error(
6080 logging_text + "kafka_write notification Exception {}".format(e)
6081 )
tierno59d22d22018-09-25 18:10:19 +02006082 self.logger.debug(logging_text + "Exit")
6083 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00006084
aktas5f75f102021-03-15 11:26:10 +03006085 async def _scale_kdu(
6086 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6087 ):
6088 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
6089 for kdu_name in _scaling_info:
6090 for kdu_scaling_info in _scaling_info[kdu_name]:
6091 deployed_kdu, index = get_deployed_kdu(
6092 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
6093 )
6094 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6095 kdu_instance = deployed_kdu["kdu-instance"]
6096 scale = int(kdu_scaling_info["scale"])
6097 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6098
6099 db_dict = {
6100 "collection": "nsrs",
6101 "filter": {"_id": nsr_id},
6102 "path": "_admin.deployed.K8s.{}".format(index),
6103 }
6104
6105 step = "scaling application {}".format(
6106 kdu_scaling_info["resource-name"]
6107 )
6108 self.logger.debug(logging_text + step)
6109
6110 if kdu_scaling_info["type"] == "delete":
6111 kdu_config = get_configuration(db_vnfd, kdu_name)
6112 if (
6113 kdu_config
6114 and kdu_config.get("terminate-config-primitive")
6115 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6116 ):
6117 terminate_config_primitive_list = kdu_config.get(
6118 "terminate-config-primitive"
6119 )
6120 terminate_config_primitive_list.sort(
6121 key=lambda val: int(val["seq"])
6122 )
6123
6124 for (
6125 terminate_config_primitive
6126 ) in terminate_config_primitive_list:
6127 primitive_params_ = self._map_primitive_params(
6128 terminate_config_primitive, {}, {}
6129 )
6130 step = "execute terminate config primitive"
6131 self.logger.debug(logging_text + step)
6132 await asyncio.wait_for(
6133 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6134 cluster_uuid=cluster_uuid,
6135 kdu_instance=kdu_instance,
6136 primitive_name=terminate_config_primitive["name"],
6137 params=primitive_params_,
6138 db_dict=db_dict,
6139 vca_id=vca_id,
6140 ),
6141 timeout=600,
6142 )
6143
6144 await asyncio.wait_for(
6145 self.k8scluster_map[k8s_cluster_type].scale(
6146 kdu_instance,
6147 scale,
6148 kdu_scaling_info["resource-name"],
6149 vca_id=vca_id,
6150 ),
6151 timeout=self.timeout_vca_on_error,
6152 )
6153
6154 if kdu_scaling_info["type"] == "create":
6155 kdu_config = get_configuration(db_vnfd, kdu_name)
6156 if (
6157 kdu_config
6158 and kdu_config.get("initial-config-primitive")
6159 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6160 ):
6161 initial_config_primitive_list = kdu_config.get(
6162 "initial-config-primitive"
6163 )
6164 initial_config_primitive_list.sort(
6165 key=lambda val: int(val["seq"])
6166 )
6167
6168 for initial_config_primitive in initial_config_primitive_list:
6169 primitive_params_ = self._map_primitive_params(
6170 initial_config_primitive, {}, {}
6171 )
6172 step = "execute initial config primitive"
6173 self.logger.debug(logging_text + step)
6174 await asyncio.wait_for(
6175 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6176 cluster_uuid=cluster_uuid,
6177 kdu_instance=kdu_instance,
6178 primitive_name=initial_config_primitive["name"],
6179 params=primitive_params_,
6180 db_dict=db_dict,
6181 vca_id=vca_id,
6182 ),
6183 timeout=600,
6184 )
6185
garciadeblas5697b8b2021-03-24 09:17:02 +01006186 async def _scale_ng_ro(
6187 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
6188 ):
tierno2357f4e2020-10-19 16:38:59 +00006189 nsr_id = db_nslcmop["nsInstanceId"]
6190 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
6191 db_vnfrs = {}
6192
6193 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03006194 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00006195
6196 # for each vnf in ns, read vnfd
6197 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
6198 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
6199 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00006200 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03006201 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00006202 # read from db
6203 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03006204 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00006205 n2vc_key = self.n2vc.get_public_key()
6206 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01006207 self.scale_vnfr(
6208 db_vnfr,
6209 vdu_scaling_info.get("vdu-create"),
6210 vdu_scaling_info.get("vdu-delete"),
6211 mark_delete=True,
6212 )
tierno2357f4e2020-10-19 16:38:59 +00006213 # db_vnfr has been updated, update db_vnfrs to use it
6214 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01006215 await self._instantiate_ng_ro(
6216 logging_text,
6217 nsr_id,
6218 db_nsd,
6219 db_nsr,
6220 db_nslcmop,
6221 db_vnfrs,
6222 db_vnfds,
6223 n2vc_key_list,
6224 stage=stage,
6225 start_deploy=time(),
6226 timeout_ns_deploy=self.timeout_ns_deploy,
6227 )
tierno2357f4e2020-10-19 16:38:59 +00006228 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006229 self.scale_vnfr(
6230 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
6231 )
tierno2357f4e2020-10-19 16:38:59 +00006232
garciadeblas5697b8b2021-03-24 09:17:02 +01006233 async def add_prometheus_metrics(
6234 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
6235 ):
tiernob996d942020-07-03 14:52:28 +00006236 if not self.prometheus:
6237 return
6238 # look if exist a file called 'prometheus*.j2' and
6239 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01006240 job_file = next(
6241 (
6242 f
6243 for f in artifact_content
6244 if f.startswith("prometheus") and f.endswith(".j2")
6245 ),
6246 None,
6247 )
tiernob996d942020-07-03 14:52:28 +00006248 if not job_file:
6249 return
6250 with self.fs.file_open((artifact_path, job_file), "r") as f:
6251 job_data = f.read()
6252
6253 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01006254 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00006255 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
6256 host_port = "80"
6257 vnfr_id = vnfr_id.replace("-", "")
6258 variables = {
6259 "JOB_NAME": vnfr_id,
6260 "TARGET_IP": target_ip,
6261 "EXPORTER_POD_IP": host_name,
6262 "EXPORTER_POD_PORT": host_port,
6263 }
6264 job_list = self.prometheus.parse_job(job_data, variables)
6265 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
6266 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01006267 if (
6268 not isinstance(job.get("job_name"), str)
6269 or vnfr_id not in job["job_name"]
6270 ):
tiernob996d942020-07-03 14:52:28 +00006271 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
6272 job["nsr_id"] = nsr_id
6273 job_dict = {jl["job_name"]: jl for jl in job_list}
6274 if await self.prometheus.update(job_dict):
6275 return list(job_dict.keys())
David Garciaaae391f2020-11-09 11:12:54 +01006276
6277 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6278 """
6279 Get VCA Cloud and VCA 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_cloud"), config.get("vca_cloud_credential")
6287
6288 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6289 """
6290 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
6291
6292 :param: vim_account_id: VIM Account ID
6293
6294 :return: (cloud_name, cloud_credential)
6295 """
bravof922c4172020-11-24 21:21:43 -03006296 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006297 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")