blob: e5cb49256e6c3b57be6ef912edf88e9fde2a2701 [file] [log] [blame]
tierno59d22d22018-09-25 18:10:19 +02001# -*- coding: utf-8 -*-
2
tierno2e215512018-11-28 09:37:52 +00003##
4# Copyright 2018 Telefonica S.A.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17##
18
tierno59d22d22018-09-25 18:10:19 +020019import asyncio
20import yaml
21import logging
22import logging.handlers
tierno59d22d22018-09-25 18:10:19 +020023import traceback
David Garciad4816682019-12-09 14:57:43 +010024import json
garciadeblas5697b8b2021-03-24 09:17:02 +010025from jinja2 import (
26 Environment,
27 TemplateError,
28 TemplateNotFound,
29 StrictUndefined,
30 UndefinedError,
31)
tierno59d22d22018-09-25 18:10:19 +020032
tierno77677d92019-08-22 13:46:35 +000033from osm_lcm import ROclient
aktas5f75f102021-03-15 11:26:10 +030034from osm_lcm.data_utils.nsr import get_deployed_kdu
tierno69f0d382020-05-07 13:08:09 +000035from osm_lcm.ng_ro import NgRoClient, NgRoException
garciadeblas5697b8b2021-03-24 09:17:02 +010036from osm_lcm.lcm_utils import (
37 LcmException,
38 LcmExceptionNoMgmtIP,
39 LcmBase,
40 deep_get,
41 get_iterable,
42 populate_dict,
43)
bravof922c4172020-11-24 21:21:43 -030044from osm_lcm.data_utils.nsd import get_vnf_profiles
garciadeblas5697b8b2021-03-24 09:17:02 +010045from osm_lcm.data_utils.vnfd import (
46 get_vdu_list,
47 get_vdu_profile,
48 get_ee_sorted_initial_config_primitive_list,
49 get_ee_sorted_terminate_config_primitive_list,
50 get_kdu_list,
51 get_virtual_link_profiles,
52 get_vdu,
53 get_configuration,
54 get_vdu_index,
55 get_scaling_aspect,
56 get_number_of_instances,
57 get_juju_ee_ref,
aktas5f75f102021-03-15 11:26:10 +030058 get_kdu_profile,
garciadeblas5697b8b2021-03-24 09:17:02 +010059)
bravof922c4172020-11-24 21:21:43 -030060from osm_lcm.data_utils.list_utils import find_in_list
aktas5f75f102021-03-15 11:26:10 +030061from osm_lcm.data_utils.vnfr import get_osm_params, get_vdur_index, get_kdur
bravof922c4172020-11-24 21:21:43 -030062from osm_lcm.data_utils.dict_utils import parse_yaml_strings
63from osm_lcm.data_utils.database.vim_account import VimAccountDB
calvinosanch9f9c6f22019-11-04 13:37:39 +010064from n2vc.k8s_helm_conn import K8sHelmConnector
lloretgalleg18ebc3a2020-10-22 09:54:51 +000065from n2vc.k8s_helm3_conn import K8sHelm3Connector
Adam Israelbaacc302019-12-01 12:41:39 -050066from n2vc.k8s_juju_conn import K8sJujuConnector
tierno59d22d22018-09-25 18:10:19 +020067
tierno27246d82018-09-27 15:59:09 +020068from osm_common.dbbase import DbException
tierno59d22d22018-09-25 18:10:19 +020069from osm_common.fsbase import FsException
quilesj7e13aeb2019-10-08 13:34:55 +020070
bravof922c4172020-11-24 21:21:43 -030071from osm_lcm.data_utils.database.database import Database
72from osm_lcm.data_utils.filesystem.filesystem import Filesystem
73
quilesj7e13aeb2019-10-08 13:34:55 +020074from n2vc.n2vc_juju_conn import N2VCJujuConnector
tiernof59ad6c2020-04-08 12:50:52 +000075from n2vc.exceptions import N2VCException, N2VCNotFound, K8sException
tierno59d22d22018-09-25 18:10:19 +020076
tierno588547c2020-07-01 15:30:20 +000077from osm_lcm.lcm_helm_conn import LCMHelmConn
78
tierno27246d82018-09-27 15:59:09 +020079from copy import copy, deepcopy
tierno59d22d22018-09-25 18:10:19 +020080from time import time
tierno27246d82018-09-27 15:59:09 +020081from uuid import uuid4
lloretgalleg7c121132020-07-08 07:53:22 +000082
tiernob996d942020-07-03 14:52:28 +000083from random import randint
tierno59d22d22018-09-25 18:10:19 +020084
tierno69f0d382020-05-07 13:08:09 +000085__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
tierno59d22d22018-09-25 18:10:19 +020086
87
88class NsLcm(LcmBase):
garciadeblas5697b8b2021-03-24 09:17:02 +010089 timeout_vca_on_error = (
90 5 * 60
91 ) # Time for charm from first time at blocked,error status to mark as failed
92 timeout_ns_deploy = 2 * 3600 # default global timeout for deployment a ns
93 timeout_ns_terminate = 1800 # default global timeout for un deployment a ns
garciadeblasf9b04952019-04-09 18:53:58 +020094 timeout_charm_delete = 10 * 60
David Garciaf6919842020-05-21 16:41:07 +020095 timeout_primitive = 30 * 60 # timeout for primitive execution
garciadeblas5697b8b2021-03-24 09:17:02 +010096 timeout_progress_primitive = (
97 10 * 60
98 ) # timeout for some progress in a primitive execution
tierno59d22d22018-09-25 18:10:19 +020099
kuuseac3a8882019-10-03 10:48:06 +0200100 SUBOPERATION_STATUS_NOT_FOUND = -1
101 SUBOPERATION_STATUS_NEW = -2
102 SUBOPERATION_STATUS_SKIP = -3
tiernoa2143262020-03-27 16:20:40 +0000103 task_name_deploy_vca = "Deploying VCA"
kuuseac3a8882019-10-03 10:48:06 +0200104
bravof922c4172020-11-24 21:21:43 -0300105 def __init__(self, msg, lcm_tasks, config, loop, prometheus=None):
tierno59d22d22018-09-25 18:10:19 +0200106 """
107 Init, Connect to database, filesystem storage, and messaging
108 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
109 :return: None
110 """
garciadeblas5697b8b2021-03-24 09:17:02 +0100111 super().__init__(msg=msg, logger=logging.getLogger("lcm.ns"))
quilesj7e13aeb2019-10-08 13:34:55 +0200112
bravof922c4172020-11-24 21:21:43 -0300113 self.db = Database().instance.db
114 self.fs = Filesystem().instance.fs
tierno59d22d22018-09-25 18:10:19 +0200115 self.loop = loop
116 self.lcm_tasks = lcm_tasks
tierno744303e2020-01-13 16:46:31 +0000117 self.timeout = config["timeout"]
118 self.ro_config = config["ro_config"]
tierno69f0d382020-05-07 13:08:09 +0000119 self.ng_ro = config["ro_config"].get("ng")
tierno744303e2020-01-13 16:46:31 +0000120 self.vca_config = config["VCA"].copy()
tierno59d22d22018-09-25 18:10:19 +0200121
quilesj7e13aeb2019-10-08 13:34:55 +0200122 # create N2VC connector
David Garciaaae391f2020-11-09 11:12:54 +0100123 self.n2vc = N2VCJujuConnector(
tierno59d22d22018-09-25 18:10:19 +0200124 log=self.logger,
quilesj7e13aeb2019-10-08 13:34:55 +0200125 loop=self.loop,
bravof922c4172020-11-24 21:21:43 -0300126 on_update_db=self._on_update_n2vc_db,
127 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100128 db=self.db,
tierno59d22d22018-09-25 18:10:19 +0200129 )
quilesj7e13aeb2019-10-08 13:34:55 +0200130
tierno588547c2020-07-01 15:30:20 +0000131 self.conn_helm_ee = LCMHelmConn(
tierno588547c2020-07-01 15:30:20 +0000132 log=self.logger,
133 loop=self.loop,
tierno588547c2020-07-01 15:30:20 +0000134 vca_config=self.vca_config,
garciadeblas5697b8b2021-03-24 09:17:02 +0100135 on_update_db=self._on_update_n2vc_db,
tierno588547c2020-07-01 15:30:20 +0000136 )
137
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000138 self.k8sclusterhelm2 = K8sHelmConnector(
calvinosanch9f9c6f22019-11-04 13:37:39 +0100139 kubectl_command=self.vca_config.get("kubectlpath"),
140 helm_command=self.vca_config.get("helmpath"),
calvinosanch9f9c6f22019-11-04 13:37:39 +0100141 log=self.logger,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100142 on_update_db=None,
bravof922c4172020-11-24 21:21:43 -0300143 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100144 db=self.db,
calvinosanch9f9c6f22019-11-04 13:37:39 +0100145 )
146
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000147 self.k8sclusterhelm3 = K8sHelm3Connector(
148 kubectl_command=self.vca_config.get("kubectlpath"),
149 helm_command=self.vca_config.get("helm3path"),
150 fs=self.fs,
151 log=self.logger,
152 db=self.db,
153 on_update_db=None,
154 )
155
Adam Israelbaacc302019-12-01 12:41:39 -0500156 self.k8sclusterjuju = K8sJujuConnector(
157 kubectl_command=self.vca_config.get("kubectlpath"),
158 juju_command=self.vca_config.get("jujupath"),
Adam Israelbaacc302019-12-01 12:41:39 -0500159 log=self.logger,
David Garciaba89cbb2020-10-16 13:05:34 +0200160 loop=self.loop,
ksaikiranr656b6dd2021-02-19 10:25:18 +0530161 on_update_db=self._on_update_k8s_db,
bravof922c4172020-11-24 21:21:43 -0300162 fs=self.fs,
garciadeblas5697b8b2021-03-24 09:17:02 +0100163 db=self.db,
Adam Israelbaacc302019-12-01 12:41:39 -0500164 )
165
tiernoa2143262020-03-27 16:20:40 +0000166 self.k8scluster_map = {
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000167 "helm-chart": self.k8sclusterhelm2,
168 "helm-chart-v3": self.k8sclusterhelm3,
169 "chart": self.k8sclusterhelm3,
tiernoa2143262020-03-27 16:20:40 +0000170 "juju-bundle": self.k8sclusterjuju,
171 "juju": self.k8sclusterjuju,
172 }
tierno588547c2020-07-01 15:30:20 +0000173
174 self.vca_map = {
175 "lxc_proxy_charm": self.n2vc,
176 "native_charm": self.n2vc,
177 "k8s_proxy_charm": self.n2vc,
lloretgalleg18ebc3a2020-10-22 09:54:51 +0000178 "helm": self.conn_helm_ee,
garciadeblas5697b8b2021-03-24 09:17:02 +0100179 "helm-v3": self.conn_helm_ee,
tierno588547c2020-07-01 15:30:20 +0000180 }
181
tiernob996d942020-07-03 14:52:28 +0000182 self.prometheus = prometheus
183
quilesj7e13aeb2019-10-08 13:34:55 +0200184 # create RO client
bravof922c4172020-11-24 21:21:43 -0300185 self.RO = NgRoClient(self.loop, **self.ro_config)
tierno59d22d22018-09-25 18:10:19 +0200186
tierno2357f4e2020-10-19 16:38:59 +0000187 @staticmethod
188 def increment_ip_mac(ip_mac, vm_index=1):
189 if not isinstance(ip_mac, str):
190 return ip_mac
191 try:
192 # try with ipv4 look for last dot
193 i = ip_mac.rfind(".")
194 if i > 0:
195 i += 1
196 return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index)
197 # try with ipv6 or mac look for last colon. Operate in hex
198 i = ip_mac.rfind(":")
199 if i > 0:
200 i += 1
201 # format in hex, len can be 2 for mac or 4 for ipv6
garciadeblas5697b8b2021-03-24 09:17:02 +0100202 return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(
203 ip_mac[:i], int(ip_mac[i:], 16) + vm_index
204 )
tierno2357f4e2020-10-19 16:38:59 +0000205 except Exception:
206 pass
207 return None
208
quilesj3655ae02019-12-12 16:08:35 +0000209 def _on_update_ro_db(self, nsrs_id, ro_descriptor):
quilesj7e13aeb2019-10-08 13:34:55 +0200210
quilesj3655ae02019-12-12 16:08:35 +0000211 # self.logger.debug('_on_update_ro_db(nsrs_id={}'.format(nsrs_id))
212
213 try:
214 # TODO filter RO descriptor fields...
215
216 # write to database
217 db_dict = dict()
218 # db_dict['deploymentStatus'] = yaml.dump(ro_descriptor, default_flow_style=False, indent=2)
garciadeblas5697b8b2021-03-24 09:17:02 +0100219 db_dict["deploymentStatus"] = ro_descriptor
quilesj3655ae02019-12-12 16:08:35 +0000220 self.update_db_2("nsrs", nsrs_id, db_dict)
221
222 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100223 self.logger.warn(
224 "Cannot write database RO deployment for ns={} -> {}".format(nsrs_id, e)
225 )
quilesj3655ae02019-12-12 16:08:35 +0000226
David Garciac1fe90a2021-03-31 19:12:02 +0200227 async def _on_update_n2vc_db(self, table, filter, path, updated_data, vca_id=None):
quilesj3655ae02019-12-12 16:08:35 +0000228
quilesj69a722c2020-01-09 08:30:17 +0000229 # remove last dot from path (if exists)
garciadeblas5697b8b2021-03-24 09:17:02 +0100230 if path.endswith("."):
quilesj69a722c2020-01-09 08:30:17 +0000231 path = path[:-1]
232
quilesj3655ae02019-12-12 16:08:35 +0000233 # self.logger.debug('_on_update_n2vc_db(table={}, filter={}, path={}, updated_data={}'
234 # .format(table, filter, path, updated_data))
quilesj3655ae02019-12-12 16:08:35 +0000235 try:
236
garciadeblas5697b8b2021-03-24 09:17:02 +0100237 nsr_id = filter.get("_id")
quilesj3655ae02019-12-12 16:08:35 +0000238
239 # read ns record from database
garciadeblas5697b8b2021-03-24 09:17:02 +0100240 nsr = self.db.get_one(table="nsrs", q_filter=filter)
241 current_ns_status = nsr.get("nsState")
quilesj3655ae02019-12-12 16:08:35 +0000242
243 # get vca status for NS
garciadeblas5697b8b2021-03-24 09:17:02 +0100244 status_dict = await self.n2vc.get_status(
245 namespace="." + nsr_id, yaml_format=False, vca_id=vca_id
246 )
quilesj3655ae02019-12-12 16:08:35 +0000247
248 # vcaStatus
249 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100250 db_dict["vcaStatus"] = status_dict
251 await self.n2vc.update_vca_status(db_dict["vcaStatus"], vca_id=vca_id)
quilesj3655ae02019-12-12 16:08:35 +0000252
253 # update configurationStatus for this VCA
254 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100255 vca_index = int(path[path.rfind(".") + 1 :])
quilesj3655ae02019-12-12 16:08:35 +0000256
garciadeblas5697b8b2021-03-24 09:17:02 +0100257 vca_list = deep_get(
258 target_dict=nsr, key_list=("_admin", "deployed", "VCA")
259 )
260 vca_status = vca_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000261
garciadeblas5697b8b2021-03-24 09:17:02 +0100262 configuration_status_list = nsr.get("configurationStatus")
263 config_status = configuration_status_list[vca_index].get("status")
quilesj3655ae02019-12-12 16:08:35 +0000264
garciadeblas5697b8b2021-03-24 09:17:02 +0100265 if config_status == "BROKEN" and vca_status != "failed":
266 db_dict["configurationStatus"][vca_index] = "READY"
267 elif config_status != "BROKEN" and vca_status == "failed":
268 db_dict["configurationStatus"][vca_index] = "BROKEN"
quilesj3655ae02019-12-12 16:08:35 +0000269 except Exception as e:
270 # not update configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +0100271 self.logger.debug("Error updating vca_index (ignore): {}".format(e))
quilesj3655ae02019-12-12 16:08:35 +0000272
273 # if nsState = 'READY' check if juju is reporting some error => nsState = 'DEGRADED'
274 # if nsState = 'DEGRADED' check if all is OK
275 is_degraded = False
garciadeblas5697b8b2021-03-24 09:17:02 +0100276 if current_ns_status in ("READY", "DEGRADED"):
277 error_description = ""
quilesj3655ae02019-12-12 16:08:35 +0000278 # check machines
garciadeblas5697b8b2021-03-24 09:17:02 +0100279 if status_dict.get("machines"):
280 for machine_id in status_dict.get("machines"):
281 machine = status_dict.get("machines").get(machine_id)
quilesj3655ae02019-12-12 16:08:35 +0000282 # check machine agent-status
garciadeblas5697b8b2021-03-24 09:17:02 +0100283 if machine.get("agent-status"):
284 s = machine.get("agent-status").get("status")
285 if s != "started":
quilesj3655ae02019-12-12 16:08:35 +0000286 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100287 error_description += (
288 "machine {} agent-status={} ; ".format(
289 machine_id, s
290 )
291 )
quilesj3655ae02019-12-12 16:08:35 +0000292 # check machine instance status
garciadeblas5697b8b2021-03-24 09:17:02 +0100293 if machine.get("instance-status"):
294 s = machine.get("instance-status").get("status")
295 if s != "running":
quilesj3655ae02019-12-12 16:08:35 +0000296 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100297 error_description += (
298 "machine {} instance-status={} ; ".format(
299 machine_id, s
300 )
301 )
quilesj3655ae02019-12-12 16:08:35 +0000302 # check applications
garciadeblas5697b8b2021-03-24 09:17:02 +0100303 if status_dict.get("applications"):
304 for app_id in status_dict.get("applications"):
305 app = status_dict.get("applications").get(app_id)
quilesj3655ae02019-12-12 16:08:35 +0000306 # check application status
garciadeblas5697b8b2021-03-24 09:17:02 +0100307 if app.get("status"):
308 s = app.get("status").get("status")
309 if s != "active":
quilesj3655ae02019-12-12 16:08:35 +0000310 is_degraded = True
garciadeblas5697b8b2021-03-24 09:17:02 +0100311 error_description += (
312 "application {} status={} ; ".format(app_id, s)
313 )
quilesj3655ae02019-12-12 16:08:35 +0000314
315 if error_description:
garciadeblas5697b8b2021-03-24 09:17:02 +0100316 db_dict["errorDescription"] = error_description
317 if current_ns_status == "READY" and is_degraded:
318 db_dict["nsState"] = "DEGRADED"
319 if current_ns_status == "DEGRADED" and not is_degraded:
320 db_dict["nsState"] = "READY"
quilesj3655ae02019-12-12 16:08:35 +0000321
322 # write to database
323 self.update_db_2("nsrs", nsr_id, db_dict)
324
tierno51183952020-04-03 15:48:18 +0000325 except (asyncio.CancelledError, asyncio.TimeoutError):
326 raise
quilesj3655ae02019-12-12 16:08:35 +0000327 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100328 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
quilesj7e13aeb2019-10-08 13:34:55 +0200329
garciadeblas5697b8b2021-03-24 09:17:02 +0100330 async def _on_update_k8s_db(
331 self, cluster_uuid, kdu_instance, filter=None, vca_id=None
332 ):
ksaikiranr656b6dd2021-02-19 10:25:18 +0530333 """
334 Updating vca status in NSR record
335 :param cluster_uuid: UUID of a k8s cluster
336 :param kdu_instance: The unique name of the KDU instance
337 :param filter: To get nsr_id
338 :return: none
339 """
340
341 # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}"
342 # .format(cluster_uuid, kdu_instance, filter))
343
344 try:
garciadeblas5697b8b2021-03-24 09:17:02 +0100345 nsr_id = filter.get("_id")
ksaikiranr656b6dd2021-02-19 10:25:18 +0530346
347 # get vca status for NS
David Garciac1fe90a2021-03-31 19:12:02 +0200348 vca_status = await self.k8sclusterjuju.status_kdu(
349 cluster_uuid,
350 kdu_instance,
351 complete_status=True,
352 yaml_format=False,
353 vca_id=vca_id,
354 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530355 # vcaStatus
356 db_dict = dict()
garciadeblas5697b8b2021-03-24 09:17:02 +0100357 db_dict["vcaStatus"] = {nsr_id: vca_status}
ksaikiranr656b6dd2021-02-19 10:25:18 +0530358
David Garciac1fe90a2021-03-31 19:12:02 +0200359 await self.k8sclusterjuju.update_vca_status(
garciadeblas5697b8b2021-03-24 09:17:02 +0100360 db_dict["vcaStatus"],
David Garciac1fe90a2021-03-31 19:12:02 +0200361 kdu_instance,
362 vca_id=vca_id,
363 )
ksaikiranr656b6dd2021-02-19 10:25:18 +0530364
365 # write to database
366 self.update_db_2("nsrs", nsr_id, db_dict)
367
368 except (asyncio.CancelledError, asyncio.TimeoutError):
369 raise
370 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100371 self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e))
ksaikiranr656b6dd2021-02-19 10:25:18 +0530372
tierno72ef84f2020-10-06 08:22:07 +0000373 @staticmethod
374 def _parse_cloud_init(cloud_init_text, additional_params, vnfd_id, vdu_id):
375 try:
376 env = Environment(undefined=StrictUndefined)
377 template = env.from_string(cloud_init_text)
378 return template.render(additional_params or {})
379 except UndefinedError as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100380 raise LcmException(
381 "Variable {} at vnfd[id={}]:vdu[id={}]:cloud-init/cloud-init-"
382 "file, must be provided in the instantiation parameters inside the "
383 "'additionalParamsForVnf/Vdu' block".format(e, vnfd_id, vdu_id)
384 )
tierno72ef84f2020-10-06 08:22:07 +0000385 except (TemplateError, TemplateNotFound) as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100386 raise LcmException(
387 "Error parsing Jinja2 to cloud-init content at vnfd[id={}]:vdu[id={}]: {}".format(
388 vnfd_id, vdu_id, e
389 )
390 )
tierno72ef84f2020-10-06 08:22:07 +0000391
bravof922c4172020-11-24 21:21:43 -0300392 def _get_vdu_cloud_init_content(self, vdu, vnfd):
393 cloud_init_content = cloud_init_file = None
tierno72ef84f2020-10-06 08:22:07 +0000394 try:
tierno72ef84f2020-10-06 08:22:07 +0000395 if vdu.get("cloud-init-file"):
396 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +0100397 cloud_init_file = "{}/{}/cloud_init/{}".format(
398 base_folder["folder"],
399 base_folder["pkg-dir"],
400 vdu["cloud-init-file"],
401 )
tierno72ef84f2020-10-06 08:22:07 +0000402 with self.fs.file_open(cloud_init_file, "r") as ci_file:
403 cloud_init_content = ci_file.read()
404 elif vdu.get("cloud-init"):
405 cloud_init_content = vdu["cloud-init"]
406
407 return cloud_init_content
408 except FsException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +0100409 raise LcmException(
410 "Error reading vnfd[id={}]:vdu[id={}]:cloud-init-file={}: {}".format(
411 vnfd["id"], vdu["id"], cloud_init_file, e
412 )
413 )
tierno72ef84f2020-10-06 08:22:07 +0000414
tierno72ef84f2020-10-06 08:22:07 +0000415 def _get_vdu_additional_params(self, db_vnfr, vdu_id):
garciadeblas5697b8b2021-03-24 09:17:02 +0100416 vdur = next(
417 vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]
418 )
tierno72ef84f2020-10-06 08:22:07 +0000419 additional_params = vdur.get("additionalParams")
bravof922c4172020-11-24 21:21:43 -0300420 return parse_yaml_strings(additional_params)
tierno72ef84f2020-10-06 08:22:07 +0000421
gcalvino35be9152018-12-20 09:33:12 +0100422 def vnfd2RO(self, vnfd, new_id=None, additionalParams=None, nsrId=None):
tierno59d22d22018-09-25 18:10:19 +0200423 """
424 Converts creates a new vnfd descriptor for RO base on input OSM IM vnfd
425 :param vnfd: input vnfd
426 :param new_id: overrides vnf id if provided
tierno8a518872018-12-21 13:42:14 +0000427 :param additionalParams: Instantiation params for VNFs provided
gcalvino35be9152018-12-20 09:33:12 +0100428 :param nsrId: Id of the NSR
tierno59d22d22018-09-25 18:10:19 +0200429 :return: copy of vnfd
430 """
tierno72ef84f2020-10-06 08:22:07 +0000431 vnfd_RO = deepcopy(vnfd)
432 # remove unused by RO configuration, monitoring, scaling and internal keys
433 vnfd_RO.pop("_id", None)
434 vnfd_RO.pop("_admin", None)
tierno72ef84f2020-10-06 08:22:07 +0000435 vnfd_RO.pop("monitoring-param", None)
436 vnfd_RO.pop("scaling-group-descriptor", None)
437 vnfd_RO.pop("kdu", None)
438 vnfd_RO.pop("k8s-cluster", None)
439 if new_id:
440 vnfd_RO["id"] = new_id
tierno8a518872018-12-21 13:42:14 +0000441
tierno72ef84f2020-10-06 08:22:07 +0000442 # parse cloud-init or cloud-init-file with the provided variables using Jinja2
443 for vdu in get_iterable(vnfd_RO, "vdu"):
444 vdu.pop("cloud-init-file", None)
445 vdu.pop("cloud-init", None)
446 return vnfd_RO
tierno59d22d22018-09-25 18:10:19 +0200447
tierno2357f4e2020-10-19 16:38:59 +0000448 @staticmethod
449 def ip_profile_2_RO(ip_profile):
450 RO_ip_profile = deepcopy(ip_profile)
451 if "dns-server" in RO_ip_profile:
452 if isinstance(RO_ip_profile["dns-server"], list):
453 RO_ip_profile["dns-address"] = []
454 for ds in RO_ip_profile.pop("dns-server"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100455 RO_ip_profile["dns-address"].append(ds["address"])
tierno2357f4e2020-10-19 16:38:59 +0000456 else:
457 RO_ip_profile["dns-address"] = RO_ip_profile.pop("dns-server")
458 if RO_ip_profile.get("ip-version") == "ipv4":
459 RO_ip_profile["ip-version"] = "IPv4"
460 if RO_ip_profile.get("ip-version") == "ipv6":
461 RO_ip_profile["ip-version"] = "IPv6"
462 if "dhcp-params" in RO_ip_profile:
463 RO_ip_profile["dhcp"] = RO_ip_profile.pop("dhcp-params")
464 return RO_ip_profile
465
bravof922c4172020-11-24 21:21:43 -0300466 def _get_ro_vim_id_for_vim_account(self, vim_account):
467 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account})
468 if db_vim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100469 raise LcmException(
470 "VIM={} is not available. operationalState={}".format(
471 vim_account, db_vim["_admin"]["operationalState"]
472 )
473 )
bravof922c4172020-11-24 21:21:43 -0300474 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
475 return RO_vim_id
tierno59d22d22018-09-25 18:10:19 +0200476
bravof922c4172020-11-24 21:21:43 -0300477 def get_ro_wim_id_for_wim_account(self, wim_account):
478 if isinstance(wim_account, str):
479 db_wim = self.db.get_one("wim_accounts", {"_id": wim_account})
480 if db_wim["_admin"]["operationalState"] != "ENABLED":
garciadeblas5697b8b2021-03-24 09:17:02 +0100481 raise LcmException(
482 "WIM={} is not available. operationalState={}".format(
483 wim_account, db_wim["_admin"]["operationalState"]
484 )
485 )
bravof922c4172020-11-24 21:21:43 -0300486 RO_wim_id = db_wim["_admin"]["deployed"]["RO-account"]
487 return RO_wim_id
488 else:
489 return wim_account
tierno59d22d22018-09-25 18:10:19 +0200490
tierno2357f4e2020-10-19 16:38:59 +0000491 def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False):
tierno27246d82018-09-27 15:59:09 +0200492
tierno2357f4e2020-10-19 16:38:59 +0000493 db_vdu_push_list = []
494 db_update = {"_admin.modified": time()}
495 if vdu_create:
496 for vdu_id, vdu_count in vdu_create.items():
garciadeblas5697b8b2021-03-24 09:17:02 +0100497 vdur = next(
498 (
499 vdur
500 for vdur in reversed(db_vnfr["vdur"])
501 if vdur["vdu-id-ref"] == vdu_id
502 ),
503 None,
504 )
tierno2357f4e2020-10-19 16:38:59 +0000505 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +0100506 raise LcmException(
507 "Error scaling OUT VNFR for {}. There is not any existing vnfr. Scaled to 0?".format(
508 vdu_id
509 )
510 )
tierno2357f4e2020-10-19 16:38:59 +0000511
512 for count in range(vdu_count):
513 vdur_copy = deepcopy(vdur)
514 vdur_copy["status"] = "BUILD"
515 vdur_copy["status-detailed"] = None
Guillermo Calvinofbf294c2022-01-26 17:40:31 +0100516 vdur_copy["ip-address"] = None
tierno683eb392020-09-25 12:33:15 +0000517 vdur_copy["_id"] = str(uuid4())
tierno2357f4e2020-10-19 16:38:59 +0000518 vdur_copy["count-index"] += count + 1
garciadeblas5697b8b2021-03-24 09:17:02 +0100519 vdur_copy["id"] = "{}-{}".format(
520 vdur_copy["vdu-id-ref"], vdur_copy["count-index"]
521 )
tierno2357f4e2020-10-19 16:38:59 +0000522 vdur_copy.pop("vim_info", None)
523 for iface in vdur_copy["interfaces"]:
524 if iface.get("fixed-ip"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100525 iface["ip-address"] = self.increment_ip_mac(
526 iface["ip-address"], count + 1
527 )
tierno2357f4e2020-10-19 16:38:59 +0000528 else:
529 iface.pop("ip-address", None)
530 if iface.get("fixed-mac"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100531 iface["mac-address"] = self.increment_ip_mac(
532 iface["mac-address"], count + 1
533 )
tierno2357f4e2020-10-19 16:38:59 +0000534 else:
535 iface.pop("mac-address", None)
garciadeblas5697b8b2021-03-24 09:17:02 +0100536 iface.pop(
537 "mgmt_vnf", None
538 ) # only first vdu can be managment of vnf
tierno2357f4e2020-10-19 16:38:59 +0000539 db_vdu_push_list.append(vdur_copy)
540 # self.logger.debug("scale out, adding vdu={}".format(vdur_copy))
tierno27246d82018-09-27 15:59:09 +0200541 if vdu_delete:
tierno2357f4e2020-10-19 16:38:59 +0000542 for vdu_id, vdu_count in vdu_delete.items():
543 if mark_delete:
garciadeblas5697b8b2021-03-24 09:17:02 +0100544 indexes_to_delete = [
545 iv[0]
546 for iv in enumerate(db_vnfr["vdur"])
547 if iv[1]["vdu-id-ref"] == vdu_id
548 ]
549 db_update.update(
550 {
551 "vdur.{}.status".format(i): "DELETING"
552 for i in indexes_to_delete[-vdu_count:]
553 }
554 )
tierno2357f4e2020-10-19 16:38:59 +0000555 else:
556 # it must be deleted one by one because common.db does not allow otherwise
garciadeblas5697b8b2021-03-24 09:17:02 +0100557 vdus_to_delete = [
558 v
559 for v in reversed(db_vnfr["vdur"])
560 if v["vdu-id-ref"] == vdu_id
561 ]
tierno2357f4e2020-10-19 16:38:59 +0000562 for vdu in vdus_to_delete[:vdu_count]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100563 self.db.set_one(
564 "vnfrs",
565 {"_id": db_vnfr["_id"]},
566 None,
567 pull={"vdur": {"_id": vdu["_id"]}},
568 )
tierno2357f4e2020-10-19 16:38:59 +0000569 db_push = {"vdur": db_vdu_push_list} if db_vdu_push_list else None
570 self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push)
571 # modify passed dictionary db_vnfr
572 db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]})
573 db_vnfr["vdur"] = db_vnfr_["vdur"]
tierno27246d82018-09-27 15:59:09 +0200574
tiernof578e552018-11-08 19:07:20 +0100575 def ns_update_nsr(self, ns_update_nsr, db_nsr, nsr_desc_RO):
576 """
577 Updates database nsr with the RO info for the created vld
578 :param ns_update_nsr: dictionary to be filled with the updated info
579 :param db_nsr: content of db_nsr. This is also modified
580 :param nsr_desc_RO: nsr descriptor from RO
581 :return: Nothing, LcmException is raised on errors
582 """
583
584 for vld_index, vld in enumerate(get_iterable(db_nsr, "vld")):
585 for net_RO in get_iterable(nsr_desc_RO, "nets"):
586 if vld["id"] != net_RO.get("ns_net_osm_id"):
587 continue
588 vld["vim-id"] = net_RO.get("vim_net_id")
589 vld["name"] = net_RO.get("vim_name")
590 vld["status"] = net_RO.get("status")
591 vld["status-detailed"] = net_RO.get("error_msg")
592 ns_update_nsr["vld.{}".format(vld_index)] = vld
593 break
594 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100595 raise LcmException(
596 "ns_update_nsr: Not found vld={} at RO info".format(vld["id"])
597 )
tiernof578e552018-11-08 19:07:20 +0100598
tiernoe876f672020-02-13 14:34:48 +0000599 def set_vnfr_at_error(self, db_vnfrs, error_text):
600 try:
601 for db_vnfr in db_vnfrs.values():
602 vnfr_update = {"status": "ERROR"}
603 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
604 if "status" not in vdur:
605 vdur["status"] = "ERROR"
606 vnfr_update["vdur.{}.status".format(vdu_index)] = "ERROR"
607 if error_text:
608 vdur["status-detailed"] = str(error_text)
garciadeblas5697b8b2021-03-24 09:17:02 +0100609 vnfr_update[
610 "vdur.{}.status-detailed".format(vdu_index)
611 ] = "ERROR"
tiernoe876f672020-02-13 14:34:48 +0000612 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
613 except DbException as e:
614 self.logger.error("Cannot update vnf. {}".format(e))
615
tierno59d22d22018-09-25 18:10:19 +0200616 def ns_update_vnfr(self, db_vnfrs, nsr_desc_RO):
617 """
618 Updates database vnfr with the RO info, e.g. ip_address, vim_id... Descriptor db_vnfrs is also updated
tierno27246d82018-09-27 15:59:09 +0200619 :param db_vnfrs: dictionary with member-vnf-index: vnfr-content
620 :param nsr_desc_RO: nsr descriptor from RO
621 :return: Nothing, LcmException is raised on errors
tierno59d22d22018-09-25 18:10:19 +0200622 """
623 for vnf_index, db_vnfr in db_vnfrs.items():
624 for vnf_RO in nsr_desc_RO["vnfs"]:
tierno27246d82018-09-27 15:59:09 +0200625 if vnf_RO["member_vnf_index"] != vnf_index:
626 continue
627 vnfr_update = {}
tiernof578e552018-11-08 19:07:20 +0100628 if vnf_RO.get("ip_address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100629 db_vnfr["ip-address"] = vnfr_update["ip-address"] = vnf_RO[
630 "ip_address"
631 ].split(";")[0]
tiernof578e552018-11-08 19:07:20 +0100632 elif not db_vnfr.get("ip-address"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100633 if db_vnfr.get("vdur"): # if not VDUs, there is not ip_address
634 raise LcmExceptionNoMgmtIP(
635 "ns member_vnf_index '{}' has no IP address".format(
636 vnf_index
637 )
638 )
tierno59d22d22018-09-25 18:10:19 +0200639
tierno27246d82018-09-27 15:59:09 +0200640 for vdu_index, vdur in enumerate(get_iterable(db_vnfr, "vdur")):
641 vdur_RO_count_index = 0
642 if vdur.get("pdu-type"):
643 continue
644 for vdur_RO in get_iterable(vnf_RO, "vms"):
645 if vdur["vdu-id-ref"] != vdur_RO["vdu_osm_id"]:
646 continue
647 if vdur["count-index"] != vdur_RO_count_index:
648 vdur_RO_count_index += 1
649 continue
650 vdur["vim-id"] = vdur_RO.get("vim_vm_id")
tierno1674de82019-04-09 13:03:14 +0000651 if vdur_RO.get("ip_address"):
652 vdur["ip-address"] = vdur_RO["ip_address"].split(";")[0]
tierno274ed572019-04-04 13:33:27 +0000653 else:
654 vdur["ip-address"] = None
tierno27246d82018-09-27 15:59:09 +0200655 vdur["vdu-id-ref"] = vdur_RO.get("vdu_osm_id")
656 vdur["name"] = vdur_RO.get("vim_name")
657 vdur["status"] = vdur_RO.get("status")
658 vdur["status-detailed"] = vdur_RO.get("error_msg")
659 for ifacer in get_iterable(vdur, "interfaces"):
660 for interface_RO in get_iterable(vdur_RO, "interfaces"):
661 if ifacer["name"] == interface_RO.get("internal_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100662 ifacer["ip-address"] = interface_RO.get(
663 "ip_address"
664 )
665 ifacer["mac-address"] = interface_RO.get(
666 "mac_address"
667 )
tierno27246d82018-09-27 15:59:09 +0200668 break
669 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100670 raise LcmException(
671 "ns_update_vnfr: Not found member_vnf_index={} vdur={} interface={} "
672 "from VIM info".format(
673 vnf_index, vdur["vdu-id-ref"], ifacer["name"]
674 )
675 )
tierno27246d82018-09-27 15:59:09 +0200676 vnfr_update["vdur.{}".format(vdu_index)] = vdur
677 break
678 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100679 raise LcmException(
680 "ns_update_vnfr: Not found member_vnf_index={} vdur={} count_index={} from "
681 "VIM info".format(
682 vnf_index, vdur["vdu-id-ref"], vdur["count-index"]
683 )
684 )
tiernof578e552018-11-08 19:07:20 +0100685
686 for vld_index, vld in enumerate(get_iterable(db_vnfr, "vld")):
687 for net_RO in get_iterable(nsr_desc_RO, "nets"):
688 if vld["id"] != net_RO.get("vnf_net_osm_id"):
689 continue
690 vld["vim-id"] = net_RO.get("vim_net_id")
691 vld["name"] = net_RO.get("vim_name")
692 vld["status"] = net_RO.get("status")
693 vld["status-detailed"] = net_RO.get("error_msg")
694 vnfr_update["vld.{}".format(vld_index)] = vld
695 break
696 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100697 raise LcmException(
698 "ns_update_vnfr: Not found member_vnf_index={} vld={} from VIM info".format(
699 vnf_index, vld["id"]
700 )
701 )
tiernof578e552018-11-08 19:07:20 +0100702
tierno27246d82018-09-27 15:59:09 +0200703 self.update_db_2("vnfrs", db_vnfr["_id"], vnfr_update)
704 break
tierno59d22d22018-09-25 18:10:19 +0200705
706 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100707 raise LcmException(
708 "ns_update_vnfr: Not found member_vnf_index={} from VIM info".format(
709 vnf_index
710 )
711 )
tierno59d22d22018-09-25 18:10:19 +0200712
tierno5ee02052019-12-05 19:55:02 +0000713 def _get_ns_config_info(self, nsr_id):
tiernoc3f2a822019-11-05 13:45:04 +0000714 """
715 Generates a mapping between vnf,vdu elements and the N2VC id
tierno5ee02052019-12-05 19:55:02 +0000716 :param nsr_id: id of nsr to get last database _admin.deployed.VCA that contains this list
tiernoc3f2a822019-11-05 13:45:04 +0000717 :return: a dictionary with {osm-config-mapping: {}} where its element contains:
718 "<member-vnf-index>": <N2VC-id> for a vnf configuration, or
719 "<member-vnf-index>.<vdu.id>.<vdu replica(0, 1,..)>": <N2VC-id> for a vdu configuration
720 """
tierno5ee02052019-12-05 19:55:02 +0000721 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
722 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernoc3f2a822019-11-05 13:45:04 +0000723 mapping = {}
724 ns_config_info = {"osm-config-mapping": mapping}
725 for vca in vca_deployed_list:
726 if not vca["member-vnf-index"]:
727 continue
728 if not vca["vdu_id"]:
729 mapping[vca["member-vnf-index"]] = vca["application"]
730 else:
garciadeblas5697b8b2021-03-24 09:17:02 +0100731 mapping[
732 "{}.{}.{}".format(
733 vca["member-vnf-index"], vca["vdu_id"], vca["vdu_count_index"]
734 )
735 ] = vca["application"]
tiernoc3f2a822019-11-05 13:45:04 +0000736 return ns_config_info
737
garciadeblas5697b8b2021-03-24 09:17:02 +0100738 async def _instantiate_ng_ro(
739 self,
740 logging_text,
741 nsr_id,
742 nsd,
743 db_nsr,
744 db_nslcmop,
745 db_vnfrs,
746 db_vnfds,
747 n2vc_key_list,
748 stage,
749 start_deploy,
750 timeout_ns_deploy,
751 ):
tierno2357f4e2020-10-19 16:38:59 +0000752
753 db_vims = {}
754
755 def get_vim_account(vim_account_id):
756 nonlocal db_vims
757 if vim_account_id in db_vims:
758 return db_vims[vim_account_id]
759 db_vim = self.db.get_one("vim_accounts", {"_id": vim_account_id})
760 db_vims[vim_account_id] = db_vim
761 return db_vim
762
763 # modify target_vld info with instantiation parameters
garciadeblas5697b8b2021-03-24 09:17:02 +0100764 def parse_vld_instantiation_params(
765 target_vim, target_vld, vld_params, target_sdn
766 ):
tierno2357f4e2020-10-19 16:38:59 +0000767 if vld_params.get("ip-profile"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100768 target_vld["vim_info"][target_vim]["ip_profile"] = vld_params[
769 "ip-profile"
770 ]
tierno2357f4e2020-10-19 16:38:59 +0000771 if vld_params.get("provider-network"):
garciadeblas5697b8b2021-03-24 09:17:02 +0100772 target_vld["vim_info"][target_vim]["provider_network"] = vld_params[
773 "provider-network"
774 ]
tierno2357f4e2020-10-19 16:38:59 +0000775 if "sdn-ports" in vld_params["provider-network"] and target_sdn:
garciadeblas5697b8b2021-03-24 09:17:02 +0100776 target_vld["vim_info"][target_sdn]["sdn-ports"] = vld_params[
777 "provider-network"
778 ]["sdn-ports"]
tierno2357f4e2020-10-19 16:38:59 +0000779 if vld_params.get("wimAccountId"):
780 target_wim = "wim:{}".format(vld_params["wimAccountId"])
781 target_vld["vim_info"][target_wim] = {}
782 for param in ("vim-network-name", "vim-network-id"):
783 if vld_params.get(param):
784 if isinstance(vld_params[param], dict):
garciaale04694c62021-03-02 10:49:28 -0300785 for vim, vim_net in vld_params[param].items():
bravof922c4172020-11-24 21:21:43 -0300786 other_target_vim = "vim:" + vim
garciadeblas5697b8b2021-03-24 09:17:02 +0100787 populate_dict(
788 target_vld["vim_info"],
789 (other_target_vim, param.replace("-", "_")),
790 vim_net,
791 )
tierno2357f4e2020-10-19 16:38:59 +0000792 else: # isinstance str
garciadeblas5697b8b2021-03-24 09:17:02 +0100793 target_vld["vim_info"][target_vim][
794 param.replace("-", "_")
795 ] = vld_params[param]
bravof922c4172020-11-24 21:21:43 -0300796 if vld_params.get("common_id"):
797 target_vld["common_id"] = vld_params.get("common_id")
tierno2357f4e2020-10-19 16:38:59 +0000798
tierno69f0d382020-05-07 13:08:09 +0000799 nslcmop_id = db_nslcmop["_id"]
800 target = {
801 "name": db_nsr["name"],
802 "ns": {"vld": []},
803 "vnf": [],
804 "image": deepcopy(db_nsr["image"]),
805 "flavor": deepcopy(db_nsr["flavor"]),
806 "action_id": nslcmop_id,
tierno2357f4e2020-10-19 16:38:59 +0000807 "cloud_init_content": {},
tierno69f0d382020-05-07 13:08:09 +0000808 }
809 for image in target["image"]:
tierno2357f4e2020-10-19 16:38:59 +0000810 image["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000811 for flavor in target["flavor"]:
tierno2357f4e2020-10-19 16:38:59 +0000812 flavor["vim_info"] = {}
tierno69f0d382020-05-07 13:08:09 +0000813
tierno2357f4e2020-10-19 16:38:59 +0000814 if db_nslcmop.get("lcmOperationType") != "instantiate":
815 # get parameters of instantiation:
garciadeblas5697b8b2021-03-24 09:17:02 +0100816 db_nslcmop_instantiate = self.db.get_list(
817 "nslcmops",
818 {
819 "nsInstanceId": db_nslcmop["nsInstanceId"],
820 "lcmOperationType": "instantiate",
821 },
822 )[-1]
tierno2357f4e2020-10-19 16:38:59 +0000823 ns_params = db_nslcmop_instantiate.get("operationParams")
824 else:
825 ns_params = db_nslcmop.get("operationParams")
bravof922c4172020-11-24 21:21:43 -0300826 ssh_keys_instantiation = ns_params.get("ssh_keys") or []
827 ssh_keys_all = ssh_keys_instantiation + (n2vc_key_list or [])
tierno69f0d382020-05-07 13:08:09 +0000828
829 cp2target = {}
tierno2357f4e2020-10-19 16:38:59 +0000830 for vld_index, vld in enumerate(db_nsr.get("vld")):
831 target_vim = "vim:{}".format(ns_params["vimAccountId"])
832 target_vld = {
833 "id": vld["id"],
834 "name": vld["name"],
835 "mgmt-network": vld.get("mgmt-network", False),
836 "type": vld.get("type"),
837 "vim_info": {
bravof922c4172020-11-24 21:21:43 -0300838 target_vim: {
839 "vim_network_name": vld.get("vim-network-name"),
garciadeblas5697b8b2021-03-24 09:17:02 +0100840 "vim_account_id": ns_params["vimAccountId"],
bravof922c4172020-11-24 21:21:43 -0300841 }
garciadeblas5697b8b2021-03-24 09:17:02 +0100842 },
tierno2357f4e2020-10-19 16:38:59 +0000843 }
844 # check if this network needs SDN assist
tierno2357f4e2020-10-19 16:38:59 +0000845 if vld.get("pci-interfaces"):
garciadeblasa5ae90b2021-02-12 11:26:46 +0000846 db_vim = get_vim_account(ns_params["vimAccountId"])
tierno2357f4e2020-10-19 16:38:59 +0000847 sdnc_id = db_vim["config"].get("sdn-controller")
848 if sdnc_id:
garciadeblasa5ae90b2021-02-12 11:26:46 +0000849 sdn_vld = "nsrs:{}:vld.{}".format(nsr_id, vld["id"])
850 target_sdn = "sdn:{}".format(sdnc_id)
851 target_vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100852 "sdn": True,
853 "target_vim": target_vim,
854 "vlds": [sdn_vld],
855 "type": vld.get("type"),
856 }
tierno2357f4e2020-10-19 16:38:59 +0000857
bravof922c4172020-11-24 21:21:43 -0300858 nsd_vnf_profiles = get_vnf_profiles(nsd)
859 for nsd_vnf_profile in nsd_vnf_profiles:
860 for cp in nsd_vnf_profile["virtual-link-connectivity"]:
861 if cp["virtual-link-profile-id"] == vld["id"]:
garciadeblas5697b8b2021-03-24 09:17:02 +0100862 cp2target[
863 "member_vnf:{}.{}".format(
864 cp["constituent-cpd-id"][0][
865 "constituent-base-element-id"
866 ],
867 cp["constituent-cpd-id"][0]["constituent-cpd-id"],
868 )
869 ] = "nsrs:{}:vld.{}".format(nsr_id, vld_index)
tierno2357f4e2020-10-19 16:38:59 +0000870
871 # check at nsd descriptor, if there is an ip-profile
872 vld_params = {}
lloretgalleg19008482021-04-19 11:40:18 +0000873 nsd_vlp = find_in_list(
874 get_virtual_link_profiles(nsd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100875 lambda a_link_profile: a_link_profile["virtual-link-desc-id"]
876 == vld["id"],
877 )
878 if (
879 nsd_vlp
880 and nsd_vlp.get("virtual-link-protocol-data")
881 and nsd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
882 ):
883 ip_profile_source_data = nsd_vlp["virtual-link-protocol-data"][
884 "l3-protocol-data"
885 ]
lloretgalleg19008482021-04-19 11:40:18 +0000886 ip_profile_dest_data = {}
887 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100888 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
889 "ip-version"
890 ]
lloretgalleg19008482021-04-19 11:40:18 +0000891 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100892 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
893 "cidr"
894 ]
lloretgalleg19008482021-04-19 11:40:18 +0000895 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100896 ip_profile_dest_data["gateway-address"] = ip_profile_source_data[
897 "gateway-ip"
898 ]
lloretgalleg19008482021-04-19 11:40:18 +0000899 if "dhcp-enabled" in ip_profile_source_data:
900 ip_profile_dest_data["dhcp-params"] = {
901 "enabled": ip_profile_source_data["dhcp-enabled"]
902 }
903 vld_params["ip-profile"] = ip_profile_dest_data
bravof922c4172020-11-24 21:21:43 -0300904
tierno2357f4e2020-10-19 16:38:59 +0000905 # update vld_params with instantiation params
garciadeblas5697b8b2021-03-24 09:17:02 +0100906 vld_instantiation_params = find_in_list(
907 get_iterable(ns_params, "vld"),
908 lambda a_vld: a_vld["name"] in (vld["name"], vld["id"]),
909 )
tierno2357f4e2020-10-19 16:38:59 +0000910 if vld_instantiation_params:
911 vld_params.update(vld_instantiation_params)
bravof922c4172020-11-24 21:21:43 -0300912 parse_vld_instantiation_params(target_vim, target_vld, vld_params, None)
tierno69f0d382020-05-07 13:08:09 +0000913 target["ns"]["vld"].append(target_vld)
bravof922c4172020-11-24 21:21:43 -0300914
tierno69f0d382020-05-07 13:08:09 +0000915 for vnfr in db_vnfrs.values():
garciadeblas5697b8b2021-03-24 09:17:02 +0100916 vnfd = find_in_list(
917 db_vnfds, lambda db_vnf: db_vnf["id"] == vnfr["vnfd-ref"]
918 )
919 vnf_params = find_in_list(
920 get_iterable(ns_params, "vnf"),
921 lambda a_vnf: a_vnf["member-vnf-index"] == vnfr["member-vnf-index-ref"],
922 )
tierno69f0d382020-05-07 13:08:09 +0000923 target_vnf = deepcopy(vnfr)
tierno2357f4e2020-10-19 16:38:59 +0000924 target_vim = "vim:{}".format(vnfr["vim-account-id"])
tierno69f0d382020-05-07 13:08:09 +0000925 for vld in target_vnf.get("vld", ()):
tierno2357f4e2020-10-19 16:38:59 +0000926 # check if connected to a ns.vld, to fill target'
garciadeblas5697b8b2021-03-24 09:17:02 +0100927 vnf_cp = find_in_list(
928 vnfd.get("int-virtual-link-desc", ()),
929 lambda cpd: cpd.get("id") == vld["id"],
930 )
tierno69f0d382020-05-07 13:08:09 +0000931 if vnf_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +0100932 ns_cp = "member_vnf:{}.{}".format(
933 vnfr["member-vnf-index-ref"], vnf_cp["id"]
934 )
tierno69f0d382020-05-07 13:08:09 +0000935 if cp2target.get(ns_cp):
936 vld["target"] = cp2target[ns_cp]
bravof922c4172020-11-24 21:21:43 -0300937
garciadeblas5697b8b2021-03-24 09:17:02 +0100938 vld["vim_info"] = {
939 target_vim: {"vim_network_name": vld.get("vim-network-name")}
940 }
tierno2357f4e2020-10-19 16:38:59 +0000941 # check if this network needs SDN assist
942 target_sdn = None
943 if vld.get("pci-interfaces"):
944 db_vim = get_vim_account(vnfr["vim-account-id"])
945 sdnc_id = db_vim["config"].get("sdn-controller")
946 if sdnc_id:
947 sdn_vld = "vnfrs:{}:vld.{}".format(target_vnf["_id"], vld["id"])
948 target_sdn = "sdn:{}".format(sdnc_id)
949 vld["vim_info"][target_sdn] = {
garciadeblas5697b8b2021-03-24 09:17:02 +0100950 "sdn": True,
951 "target_vim": target_vim,
952 "vlds": [sdn_vld],
953 "type": vld.get("type"),
954 }
tierno69f0d382020-05-07 13:08:09 +0000955
tierno2357f4e2020-10-19 16:38:59 +0000956 # check at vnfd descriptor, if there is an ip-profile
957 vld_params = {}
bravof922c4172020-11-24 21:21:43 -0300958 vnfd_vlp = find_in_list(
959 get_virtual_link_profiles(vnfd),
garciadeblas5697b8b2021-03-24 09:17:02 +0100960 lambda a_link_profile: a_link_profile["id"] == vld["id"],
bravof922c4172020-11-24 21:21:43 -0300961 )
garciadeblas5697b8b2021-03-24 09:17:02 +0100962 if (
963 vnfd_vlp
964 and vnfd_vlp.get("virtual-link-protocol-data")
965 and vnfd_vlp["virtual-link-protocol-data"].get("l3-protocol-data")
966 ):
967 ip_profile_source_data = vnfd_vlp["virtual-link-protocol-data"][
968 "l3-protocol-data"
969 ]
bravof922c4172020-11-24 21:21:43 -0300970 ip_profile_dest_data = {}
971 if "ip-version" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100972 ip_profile_dest_data["ip-version"] = ip_profile_source_data[
973 "ip-version"
974 ]
bravof922c4172020-11-24 21:21:43 -0300975 if "cidr" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100976 ip_profile_dest_data["subnet-address"] = ip_profile_source_data[
977 "cidr"
978 ]
bravof922c4172020-11-24 21:21:43 -0300979 if "gateway-ip" in ip_profile_source_data:
garciadeblas5697b8b2021-03-24 09:17:02 +0100980 ip_profile_dest_data[
981 "gateway-address"
982 ] = ip_profile_source_data["gateway-ip"]
bravof922c4172020-11-24 21:21:43 -0300983 if "dhcp-enabled" in ip_profile_source_data:
984 ip_profile_dest_data["dhcp-params"] = {
985 "enabled": ip_profile_source_data["dhcp-enabled"]
986 }
987
988 vld_params["ip-profile"] = ip_profile_dest_data
tierno2357f4e2020-10-19 16:38:59 +0000989 # update vld_params with instantiation params
990 if vnf_params:
garciadeblas5697b8b2021-03-24 09:17:02 +0100991 vld_instantiation_params = find_in_list(
992 get_iterable(vnf_params, "internal-vld"),
993 lambda i_vld: i_vld["name"] == vld["id"],
994 )
tierno2357f4e2020-10-19 16:38:59 +0000995 if vld_instantiation_params:
996 vld_params.update(vld_instantiation_params)
997 parse_vld_instantiation_params(target_vim, vld, vld_params, target_sdn)
998
999 vdur_list = []
tierno69f0d382020-05-07 13:08:09 +00001000 for vdur in target_vnf.get("vdur", ()):
tierno2357f4e2020-10-19 16:38:59 +00001001 if vdur.get("status") == "DELETING" or vdur.get("pdu-type"):
1002 continue # This vdu must not be created
bravof922c4172020-11-24 21:21:43 -03001003 vdur["vim_info"] = {"vim_account_id": vnfr["vim-account-id"]}
tierno69f0d382020-05-07 13:08:09 +00001004
bravof922c4172020-11-24 21:21:43 -03001005 self.logger.debug("NS > ssh_keys > {}".format(ssh_keys_all))
1006
1007 if ssh_keys_all:
bravofe5a31bc2021-02-17 19:09:12 -03001008 vdu_configuration = get_configuration(vnfd, vdur["vdu-id-ref"])
1009 vnf_configuration = get_configuration(vnfd, vnfd["id"])
garciadeblas5697b8b2021-03-24 09:17:02 +01001010 if (
1011 vdu_configuration
1012 and vdu_configuration.get("config-access")
1013 and vdu_configuration.get("config-access").get("ssh-access")
1014 ):
bravof922c4172020-11-24 21:21:43 -03001015 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001016 vdur["ssh-access-required"] = vdu_configuration[
1017 "config-access"
1018 ]["ssh-access"]["required"]
1019 elif (
1020 vnf_configuration
1021 and vnf_configuration.get("config-access")
1022 and vnf_configuration.get("config-access").get("ssh-access")
1023 and any(iface.get("mgmt-vnf") for iface in vdur["interfaces"])
1024 ):
bravof922c4172020-11-24 21:21:43 -03001025 vdur["ssh-keys"] = ssh_keys_all
garciadeblas5697b8b2021-03-24 09:17:02 +01001026 vdur["ssh-access-required"] = vnf_configuration[
1027 "config-access"
1028 ]["ssh-access"]["required"]
1029 elif ssh_keys_instantiation and find_in_list(
1030 vdur["interfaces"], lambda iface: iface.get("mgmt-vnf")
1031 ):
bravof922c4172020-11-24 21:21:43 -03001032 vdur["ssh-keys"] = ssh_keys_instantiation
tierno69f0d382020-05-07 13:08:09 +00001033
bravof922c4172020-11-24 21:21:43 -03001034 self.logger.debug("NS > vdur > {}".format(vdur))
1035
1036 vdud = get_vdu(vnfd, vdur["vdu-id-ref"])
tierno69f0d382020-05-07 13:08:09 +00001037 # cloud-init
1038 if vdud.get("cloud-init-file"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001039 vdur["cloud-init"] = "{}:file:{}".format(
1040 vnfd["_id"], vdud.get("cloud-init-file")
1041 )
tierno2357f4e2020-10-19 16:38:59 +00001042 # read file and put content at target.cloul_init_content. Avoid ng_ro to use shared package system
1043 if vdur["cloud-init"] not in target["cloud_init_content"]:
1044 base_folder = vnfd["_admin"]["storage"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001045 cloud_init_file = "{}/{}/cloud_init/{}".format(
1046 base_folder["folder"],
1047 base_folder["pkg-dir"],
1048 vdud.get("cloud-init-file"),
1049 )
tierno2357f4e2020-10-19 16:38:59 +00001050 with self.fs.file_open(cloud_init_file, "r") as ci_file:
garciadeblas5697b8b2021-03-24 09:17:02 +01001051 target["cloud_init_content"][
1052 vdur["cloud-init"]
1053 ] = ci_file.read()
tierno69f0d382020-05-07 13:08:09 +00001054 elif vdud.get("cloud-init"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001055 vdur["cloud-init"] = "{}:vdu:{}".format(
1056 vnfd["_id"], get_vdu_index(vnfd, vdur["vdu-id-ref"])
1057 )
tierno2357f4e2020-10-19 16:38:59 +00001058 # put content at target.cloul_init_content. Avoid ng_ro read vnfd descriptor
garciadeblas5697b8b2021-03-24 09:17:02 +01001059 target["cloud_init_content"][vdur["cloud-init"]] = vdud[
1060 "cloud-init"
1061 ]
tierno2357f4e2020-10-19 16:38:59 +00001062 vdur["additionalParams"] = vdur.get("additionalParams") or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01001063 deploy_params_vdu = self._format_additional_params(
1064 vdur.get("additionalParams") or {}
1065 )
1066 deploy_params_vdu["OSM"] = get_osm_params(
1067 vnfr, vdur["vdu-id-ref"], vdur["count-index"]
1068 )
tierno2357f4e2020-10-19 16:38:59 +00001069 vdur["additionalParams"] = deploy_params_vdu
tierno69f0d382020-05-07 13:08:09 +00001070
1071 # flavor
1072 ns_flavor = target["flavor"][int(vdur["ns-flavor-id"])]
tierno2357f4e2020-10-19 16:38:59 +00001073 if target_vim not in ns_flavor["vim_info"]:
1074 ns_flavor["vim_info"][target_vim] = {}
lloretgalleg7dc94672021-02-08 11:49:50 +00001075
1076 # deal with images
1077 # in case alternative images are provided we must check if they should be applied
1078 # for the vim_type, modify the vim_type taking into account
1079 ns_image_id = int(vdur["ns-image-id"])
1080 if vdur.get("alt-image-ids"):
1081 db_vim = get_vim_account(vnfr["vim-account-id"])
1082 vim_type = db_vim["vim_type"]
1083 for alt_image_id in vdur.get("alt-image-ids"):
1084 ns_alt_image = target["image"][int(alt_image_id)]
1085 if vim_type == ns_alt_image.get("vim-type"):
1086 # must use alternative image
garciadeblas5697b8b2021-03-24 09:17:02 +01001087 self.logger.debug(
1088 "use alternative image id: {}".format(alt_image_id)
1089 )
lloretgalleg7dc94672021-02-08 11:49:50 +00001090 ns_image_id = alt_image_id
1091 vdur["ns-image-id"] = ns_image_id
1092 break
1093 ns_image = target["image"][int(ns_image_id)]
tierno2357f4e2020-10-19 16:38:59 +00001094 if target_vim not in ns_image["vim_info"]:
1095 ns_image["vim_info"][target_vim] = {}
tierno69f0d382020-05-07 13:08:09 +00001096
tierno2357f4e2020-10-19 16:38:59 +00001097 vdur["vim_info"] = {target_vim: {}}
1098 # instantiation parameters
1099 # if vnf_params:
1100 # vdu_instantiation_params = next((v for v in get_iterable(vnf_params, "vdu") if v["id"] ==
1101 # vdud["id"]), None)
1102 vdur_list.append(vdur)
1103 target_vnf["vdur"] = vdur_list
tierno69f0d382020-05-07 13:08:09 +00001104 target["vnf"].append(target_vnf)
1105
1106 desc = await self.RO.deploy(nsr_id, target)
bravof922c4172020-11-24 21:21:43 -03001107 self.logger.debug("RO return > {}".format(desc))
tierno69f0d382020-05-07 13:08:09 +00001108 action_id = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01001109 await self._wait_ng_ro(
1110 nsr_id, action_id, nslcmop_id, start_deploy, timeout_ns_deploy, stage
1111 )
tierno69f0d382020-05-07 13:08:09 +00001112
1113 # Updating NSR
1114 db_nsr_update = {
1115 "_admin.deployed.RO.operational-status": "running",
garciadeblas5697b8b2021-03-24 09:17:02 +01001116 "detailed-status": " ".join(stage),
tierno69f0d382020-05-07 13:08:09 +00001117 }
1118 # db_nsr["_admin.deployed.RO.detailed-status"] = "Deployed at VIM"
1119 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1120 self._write_op_status(nslcmop_id, stage)
garciadeblas5697b8b2021-03-24 09:17:02 +01001121 self.logger.debug(
1122 logging_text + "ns deployed at RO. RO_id={}".format(action_id)
1123 )
tierno69f0d382020-05-07 13:08:09 +00001124 return
1125
garciadeblas5697b8b2021-03-24 09:17:02 +01001126 async def _wait_ng_ro(
1127 self,
1128 nsr_id,
1129 action_id,
1130 nslcmop_id=None,
1131 start_time=None,
1132 timeout=600,
1133 stage=None,
1134 ):
tierno69f0d382020-05-07 13:08:09 +00001135 detailed_status_old = None
1136 db_nsr_update = {}
tierno2357f4e2020-10-19 16:38:59 +00001137 start_time = start_time or time()
tierno69f0d382020-05-07 13:08:09 +00001138 while time() <= start_time + timeout:
1139 desc_status = await self.RO.status(nsr_id, action_id)
bravof922c4172020-11-24 21:21:43 -03001140 self.logger.debug("Wait NG RO > {}".format(desc_status))
tierno69f0d382020-05-07 13:08:09 +00001141 if desc_status["status"] == "FAILED":
1142 raise NgRoException(desc_status["details"])
1143 elif desc_status["status"] == "BUILD":
tierno2357f4e2020-10-19 16:38:59 +00001144 if stage:
1145 stage[2] = "VIM: ({})".format(desc_status["details"])
tierno69f0d382020-05-07 13:08:09 +00001146 elif desc_status["status"] == "DONE":
tierno2357f4e2020-10-19 16:38:59 +00001147 if stage:
1148 stage[2] = "Deployed at VIM"
tierno69f0d382020-05-07 13:08:09 +00001149 break
1150 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001151 assert False, "ROclient.check_ns_status returns unknown {}".format(
1152 desc_status["status"]
1153 )
tierno2357f4e2020-10-19 16:38:59 +00001154 if stage and nslcmop_id and stage[2] != detailed_status_old:
tierno69f0d382020-05-07 13:08:09 +00001155 detailed_status_old = stage[2]
1156 db_nsr_update["detailed-status"] = " ".join(stage)
1157 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1158 self._write_op_status(nslcmop_id, stage)
bravof922c4172020-11-24 21:21:43 -03001159 await asyncio.sleep(15, loop=self.loop)
tierno69f0d382020-05-07 13:08:09 +00001160 else: # timeout_ns_deploy
1161 raise NgRoException("Timeout waiting ns to deploy")
1162
garciadeblas5697b8b2021-03-24 09:17:02 +01001163 async def _terminate_ng_ro(
1164 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
1165 ):
tierno69f0d382020-05-07 13:08:09 +00001166 db_nsr_update = {}
1167 failed_detail = []
1168 action_id = None
1169 start_deploy = time()
1170 try:
1171 target = {
1172 "ns": {"vld": []},
1173 "vnf": [],
1174 "image": [],
1175 "flavor": [],
garciadeblas5697b8b2021-03-24 09:17:02 +01001176 "action_id": nslcmop_id,
tierno69f0d382020-05-07 13:08:09 +00001177 }
1178 desc = await self.RO.deploy(nsr_id, target)
1179 action_id = desc["action_id"]
1180 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = action_id
1181 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETING"
garciadeblas5697b8b2021-03-24 09:17:02 +01001182 self.logger.debug(
1183 logging_text
1184 + "ns terminate action at RO. action_id={}".format(action_id)
1185 )
tierno69f0d382020-05-07 13:08:09 +00001186
1187 # wait until done
1188 delete_timeout = 20 * 60 # 20 minutes
garciadeblas5697b8b2021-03-24 09:17:02 +01001189 await self._wait_ng_ro(
1190 nsr_id, action_id, nslcmop_id, start_deploy, delete_timeout, stage
1191 )
tierno69f0d382020-05-07 13:08:09 +00001192
1193 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
1194 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1195 # delete all nsr
1196 await self.RO.delete(nsr_id)
1197 except Exception as e:
1198 if isinstance(e, NgRoException) and e.http_code == 404: # not found
1199 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
1200 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
1201 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01001202 self.logger.debug(
1203 logging_text + "RO_action_id={} already deleted".format(action_id)
1204 )
tierno69f0d382020-05-07 13:08:09 +00001205 elif isinstance(e, NgRoException) and e.http_code == 409: # conflict
1206 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001207 self.logger.debug(
1208 logging_text
1209 + "RO_action_id={} delete conflict: {}".format(action_id, e)
1210 )
tierno69f0d382020-05-07 13:08:09 +00001211 else:
1212 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001213 self.logger.error(
1214 logging_text
1215 + "RO_action_id={} delete error: {}".format(action_id, e)
1216 )
tierno69f0d382020-05-07 13:08:09 +00001217
1218 if failed_detail:
1219 stage[2] = "Error deleting from VIM"
1220 else:
1221 stage[2] = "Deleted from VIM"
1222 db_nsr_update["detailed-status"] = " ".join(stage)
1223 self.update_db_2("nsrs", nsr_id, db_nsr_update)
1224 self._write_op_status(nslcmop_id, stage)
1225
1226 if failed_detail:
1227 raise LcmException("; ".join(failed_detail))
1228 return
1229
garciadeblas5697b8b2021-03-24 09:17:02 +01001230 async def instantiate_RO(
1231 self,
1232 logging_text,
1233 nsr_id,
1234 nsd,
1235 db_nsr,
1236 db_nslcmop,
1237 db_vnfrs,
1238 db_vnfds,
1239 n2vc_key_list,
1240 stage,
1241 ):
tiernoe95ed362020-04-23 08:24:57 +00001242 """
1243 Instantiate at RO
1244 :param logging_text: preffix text to use at logging
1245 :param nsr_id: nsr identity
1246 :param nsd: database content of ns descriptor
1247 :param db_nsr: database content of ns record
1248 :param db_nslcmop: database content of ns operation, in this case, 'instantiate'
1249 :param db_vnfrs:
bravof922c4172020-11-24 21:21:43 -03001250 :param db_vnfds: database content of vnfds, indexed by id (not _id). {id: {vnfd_object}, ...}
tiernoe95ed362020-04-23 08:24:57 +00001251 :param n2vc_key_list: ssh-public-key list to be inserted to management vdus via cloud-init
1252 :param stage: list with 3 items: [general stage, tasks, vim_specific]. This task will write over vim_specific
1253 :return: None or exception
1254 """
tiernoe876f672020-02-13 14:34:48 +00001255 try:
tiernoe876f672020-02-13 14:34:48 +00001256 start_deploy = time()
1257 ns_params = db_nslcmop.get("operationParams")
1258 if ns_params and ns_params.get("timeout_ns_deploy"):
1259 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
1260 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001261 timeout_ns_deploy = self.timeout.get(
1262 "ns_deploy", self.timeout_ns_deploy
1263 )
quilesj7e13aeb2019-10-08 13:34:55 +02001264
tiernoe876f672020-02-13 14:34:48 +00001265 # Check for and optionally request placement optimization. Database will be updated if placement activated
1266 stage[2] = "Waiting for Placement."
tierno8790a3d2020-04-23 22:49:52 +00001267 if await self._do_placement(logging_text, db_nslcmop, db_vnfrs):
1268 # in case of placement change ns_params[vimAcountId) if not present at any vnfrs
1269 for vnfr in db_vnfrs.values():
1270 if ns_params["vimAccountId"] == vnfr["vim-account-id"]:
1271 break
1272 else:
1273 ns_params["vimAccountId"] == vnfr["vim-account-id"]
quilesj7e13aeb2019-10-08 13:34:55 +02001274
garciadeblas5697b8b2021-03-24 09:17:02 +01001275 return await self._instantiate_ng_ro(
1276 logging_text,
1277 nsr_id,
1278 nsd,
1279 db_nsr,
1280 db_nslcmop,
1281 db_vnfrs,
1282 db_vnfds,
1283 n2vc_key_list,
1284 stage,
1285 start_deploy,
1286 timeout_ns_deploy,
1287 )
tierno2357f4e2020-10-19 16:38:59 +00001288 except Exception as e:
tierno067e04a2020-03-31 12:53:13 +00001289 stage[2] = "ERROR deploying at VIM"
tiernoe876f672020-02-13 14:34:48 +00001290 self.set_vnfr_at_error(db_vnfrs, str(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01001291 self.logger.error(
1292 "Error deploying at VIM {}".format(e),
1293 exc_info=not isinstance(
1294 e,
1295 (
1296 ROclient.ROClientException,
1297 LcmException,
1298 DbException,
1299 NgRoException,
1300 ),
1301 ),
1302 )
tiernoe876f672020-02-13 14:34:48 +00001303 raise
quilesj7e13aeb2019-10-08 13:34:55 +02001304
tierno7ecbc342020-09-21 14:05:39 +00001305 async def wait_kdu_up(self, logging_text, nsr_id, vnfr_id, kdu_name):
1306 """
1307 Wait for kdu to be up, get ip address
1308 :param logging_text: prefix use for logging
1309 :param nsr_id:
1310 :param vnfr_id:
1311 :param kdu_name:
1312 :return: IP address
1313 """
1314
1315 # self.logger.debug(logging_text + "Starting wait_kdu_up")
1316 nb_tries = 0
1317
1318 while nb_tries < 360:
1319 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001320 kdur = next(
1321 (
1322 x
1323 for x in get_iterable(db_vnfr, "kdur")
1324 if x.get("kdu-name") == kdu_name
1325 ),
1326 None,
1327 )
tierno7ecbc342020-09-21 14:05:39 +00001328 if not kdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001329 raise LcmException(
1330 "Not found vnfr_id={}, kdu_name={}".format(vnfr_id, kdu_name)
1331 )
tierno7ecbc342020-09-21 14:05:39 +00001332 if kdur.get("status"):
1333 if kdur["status"] in ("READY", "ENABLED"):
1334 return kdur.get("ip-address")
1335 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001336 raise LcmException(
1337 "target KDU={} is in error state".format(kdu_name)
1338 )
tierno7ecbc342020-09-21 14:05:39 +00001339
1340 await asyncio.sleep(10, loop=self.loop)
1341 nb_tries += 1
1342 raise LcmException("Timeout waiting KDU={} instantiated".format(kdu_name))
1343
garciadeblas5697b8b2021-03-24 09:17:02 +01001344 async def wait_vm_up_insert_key_ro(
1345 self, logging_text, nsr_id, vnfr_id, vdu_id, vdu_index, pub_key=None, user=None
1346 ):
tiernoa5088192019-11-26 16:12:53 +00001347 """
1348 Wait for ip addres at RO, and optionally, insert public key in virtual machine
1349 :param logging_text: prefix use for logging
1350 :param nsr_id:
1351 :param vnfr_id:
1352 :param vdu_id:
1353 :param vdu_index:
1354 :param pub_key: public ssh key to inject, None to skip
1355 :param user: user to apply the public ssh key
1356 :return: IP address
1357 """
quilesj7e13aeb2019-10-08 13:34:55 +02001358
tierno2357f4e2020-10-19 16:38:59 +00001359 self.logger.debug(logging_text + "Starting wait_vm_up_insert_key_ro")
tiernod8323042019-08-09 11:32:23 +00001360 ro_nsr_id = None
1361 ip_address = None
1362 nb_tries = 0
1363 target_vdu_id = None
quilesj3149f262019-12-03 10:58:10 +00001364 ro_retries = 0
quilesj7e13aeb2019-10-08 13:34:55 +02001365
tiernod8323042019-08-09 11:32:23 +00001366 while True:
quilesj7e13aeb2019-10-08 13:34:55 +02001367
quilesj3149f262019-12-03 10:58:10 +00001368 ro_retries += 1
1369 if ro_retries >= 360: # 1 hour
garciadeblas5697b8b2021-03-24 09:17:02 +01001370 raise LcmException(
1371 "Not found _admin.deployed.RO.nsr_id for nsr_id: {}".format(nsr_id)
1372 )
quilesj3149f262019-12-03 10:58:10 +00001373
tiernod8323042019-08-09 11:32:23 +00001374 await asyncio.sleep(10, loop=self.loop)
quilesj7e13aeb2019-10-08 13:34:55 +02001375
1376 # get ip address
tiernod8323042019-08-09 11:32:23 +00001377 if not target_vdu_id:
1378 db_vnfr = self.db.get_one("vnfrs", {"_id": vnfr_id})
quilesj3149f262019-12-03 10:58:10 +00001379
1380 if not vdu_id: # for the VNF case
tiernoe876f672020-02-13 14:34:48 +00001381 if db_vnfr.get("status") == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001382 raise LcmException(
1383 "Cannot inject ssh-key because target VNF is in error state"
1384 )
tiernod8323042019-08-09 11:32:23 +00001385 ip_address = db_vnfr.get("ip-address")
1386 if not ip_address:
1387 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001388 vdur = next(
1389 (
1390 x
1391 for x in get_iterable(db_vnfr, "vdur")
1392 if x.get("ip-address") == ip_address
1393 ),
1394 None,
1395 )
quilesj3149f262019-12-03 10:58:10 +00001396 else: # VDU case
garciadeblas5697b8b2021-03-24 09:17:02 +01001397 vdur = next(
1398 (
1399 x
1400 for x in get_iterable(db_vnfr, "vdur")
1401 if x.get("vdu-id-ref") == vdu_id
1402 and x.get("count-index") == vdu_index
1403 ),
1404 None,
1405 )
quilesj3149f262019-12-03 10:58:10 +00001406
garciadeblas5697b8b2021-03-24 09:17:02 +01001407 if (
1408 not vdur and len(db_vnfr.get("vdur", ())) == 1
1409 ): # If only one, this should be the target vdu
tierno0e8c3f02020-03-12 17:18:21 +00001410 vdur = db_vnfr["vdur"][0]
quilesj3149f262019-12-03 10:58:10 +00001411 if not vdur:
garciadeblas5697b8b2021-03-24 09:17:02 +01001412 raise LcmException(
1413 "Not found vnfr_id={}, vdu_id={}, vdu_index={}".format(
1414 vnfr_id, vdu_id, vdu_index
1415 )
1416 )
tierno2357f4e2020-10-19 16:38:59 +00001417 # New generation RO stores information at "vim_info"
1418 ng_ro_status = None
David Garciaa8bbe672020-11-19 13:06:54 +01001419 target_vim = None
tierno2357f4e2020-10-19 16:38:59 +00001420 if vdur.get("vim_info"):
garciadeblas5697b8b2021-03-24 09:17:02 +01001421 target_vim = next(
1422 t for t in vdur["vim_info"]
1423 ) # there should be only one key
tierno2357f4e2020-10-19 16:38:59 +00001424 ng_ro_status = vdur["vim_info"][target_vim].get("vim_status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001425 if (
1426 vdur.get("pdu-type")
1427 or vdur.get("status") == "ACTIVE"
1428 or ng_ro_status == "ACTIVE"
1429 ):
quilesj3149f262019-12-03 10:58:10 +00001430 ip_address = vdur.get("ip-address")
1431 if not ip_address:
1432 continue
1433 target_vdu_id = vdur["vdu-id-ref"]
bravof922c4172020-11-24 21:21:43 -03001434 elif vdur.get("status") == "ERROR" or ng_ro_status == "ERROR":
garciadeblas5697b8b2021-03-24 09:17:02 +01001435 raise LcmException(
1436 "Cannot inject ssh-key because target VM is in error state"
1437 )
quilesj3149f262019-12-03 10:58:10 +00001438
tiernod8323042019-08-09 11:32:23 +00001439 if not target_vdu_id:
1440 continue
tiernod8323042019-08-09 11:32:23 +00001441
quilesj7e13aeb2019-10-08 13:34:55 +02001442 # inject public key into machine
1443 if pub_key and user:
tierno2357f4e2020-10-19 16:38:59 +00001444 self.logger.debug(logging_text + "Inserting RO key")
bravof922c4172020-11-24 21:21:43 -03001445 self.logger.debug("SSH > PubKey > {}".format(pub_key))
tierno0e8c3f02020-03-12 17:18:21 +00001446 if vdur.get("pdu-type"):
1447 self.logger.error(logging_text + "Cannot inject ssh-ky to a PDU")
1448 return ip_address
quilesj7e13aeb2019-10-08 13:34:55 +02001449 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01001450 ro_vm_id = "{}-{}".format(
1451 db_vnfr["member-vnf-index-ref"], target_vdu_id
1452 ) # TODO add vdu_index
tierno69f0d382020-05-07 13:08:09 +00001453 if self.ng_ro:
garciadeblas5697b8b2021-03-24 09:17:02 +01001454 target = {
1455 "action": {
1456 "action": "inject_ssh_key",
1457 "key": pub_key,
1458 "user": user,
1459 },
1460 "vnf": [{"_id": vnfr_id, "vdur": [{"id": vdur["id"]}]}],
1461 }
tierno2357f4e2020-10-19 16:38:59 +00001462 desc = await self.RO.deploy(nsr_id, target)
1463 action_id = desc["action_id"]
1464 await self._wait_ng_ro(nsr_id, action_id, timeout=600)
1465 break
tierno69f0d382020-05-07 13:08:09 +00001466 else:
tierno2357f4e2020-10-19 16:38:59 +00001467 # wait until NS is deployed at RO
1468 if not ro_nsr_id:
1469 db_nsrs = self.db.get_one("nsrs", {"_id": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01001470 ro_nsr_id = deep_get(
1471 db_nsrs, ("_admin", "deployed", "RO", "nsr_id")
1472 )
tierno2357f4e2020-10-19 16:38:59 +00001473 if not ro_nsr_id:
1474 continue
tierno69f0d382020-05-07 13:08:09 +00001475 result_dict = await self.RO.create_action(
1476 item="ns",
1477 item_id_name=ro_nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01001478 descriptor={
1479 "add_public_key": pub_key,
1480 "vms": [ro_vm_id],
1481 "user": user,
1482 },
tierno69f0d382020-05-07 13:08:09 +00001483 )
1484 # result_dict contains the format {VM-id: {vim_result: 200, description: text}}
1485 if not result_dict or not isinstance(result_dict, dict):
garciadeblas5697b8b2021-03-24 09:17:02 +01001486 raise LcmException(
1487 "Unknown response from RO when injecting key"
1488 )
tierno69f0d382020-05-07 13:08:09 +00001489 for result in result_dict.values():
1490 if result.get("vim_result") == 200:
1491 break
1492 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001493 raise ROclient.ROClientException(
1494 "error injecting key: {}".format(
1495 result.get("description")
1496 )
1497 )
tierno69f0d382020-05-07 13:08:09 +00001498 break
1499 except NgRoException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01001500 raise LcmException(
1501 "Reaching max tries injecting key. Error: {}".format(e)
1502 )
quilesj7e13aeb2019-10-08 13:34:55 +02001503 except ROclient.ROClientException as e:
tiernoa5088192019-11-26 16:12:53 +00001504 if not nb_tries:
garciadeblas5697b8b2021-03-24 09:17:02 +01001505 self.logger.debug(
1506 logging_text
1507 + "error injecting key: {}. Retrying until {} seconds".format(
1508 e, 20 * 10
1509 )
1510 )
quilesj7e13aeb2019-10-08 13:34:55 +02001511 nb_tries += 1
tiernoa5088192019-11-26 16:12:53 +00001512 if nb_tries >= 20:
garciadeblas5697b8b2021-03-24 09:17:02 +01001513 raise LcmException(
1514 "Reaching max tries injecting key. Error: {}".format(e)
1515 )
quilesj7e13aeb2019-10-08 13:34:55 +02001516 else:
quilesj7e13aeb2019-10-08 13:34:55 +02001517 break
1518
1519 return ip_address
1520
tierno5ee02052019-12-05 19:55:02 +00001521 async def _wait_dependent_n2vc(self, nsr_id, vca_deployed_list, vca_index):
1522 """
1523 Wait until dependent VCA deployments have been finished. NS wait for VNFs and VDUs. VNFs for VDUs
1524 """
1525 my_vca = vca_deployed_list[vca_index]
1526 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
quilesj3655ae02019-12-12 16:08:35 +00001527 # vdu or kdu: no dependencies
tierno5ee02052019-12-05 19:55:02 +00001528 return
1529 timeout = 300
1530 while timeout >= 0:
quilesj3655ae02019-12-12 16:08:35 +00001531 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
1532 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
1533 configuration_status_list = db_nsr["configurationStatus"]
1534 for index, vca_deployed in enumerate(configuration_status_list):
tierno5ee02052019-12-05 19:55:02 +00001535 if index == vca_index:
quilesj3655ae02019-12-12 16:08:35 +00001536 # myself
tierno5ee02052019-12-05 19:55:02 +00001537 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001538 if not my_vca.get("member-vnf-index") or (
1539 vca_deployed.get("member-vnf-index")
1540 == my_vca.get("member-vnf-index")
1541 ):
quilesj3655ae02019-12-12 16:08:35 +00001542 internal_status = configuration_status_list[index].get("status")
garciadeblas5697b8b2021-03-24 09:17:02 +01001543 if internal_status == "READY":
quilesj3655ae02019-12-12 16:08:35 +00001544 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01001545 elif internal_status == "BROKEN":
1546 raise LcmException(
1547 "Configuration aborted because dependent charm/s has failed"
1548 )
quilesj3655ae02019-12-12 16:08:35 +00001549 else:
1550 break
tierno5ee02052019-12-05 19:55:02 +00001551 else:
quilesj3655ae02019-12-12 16:08:35 +00001552 # no dependencies, return
tierno5ee02052019-12-05 19:55:02 +00001553 return
1554 await asyncio.sleep(10)
1555 timeout -= 1
tierno5ee02052019-12-05 19:55:02 +00001556
1557 raise LcmException("Configuration aborted because dependent charm/s timeout")
1558
David Garciac1fe90a2021-03-31 19:12:02 +02001559 def get_vca_id(self, db_vnfr: dict, db_nsr: dict):
David Garcia0b2b1882021-10-21 17:03:48 +02001560 vca_id = None
1561 if db_vnfr:
1562 vca_id = deep_get(db_vnfr, ("vca-id",))
1563 elif db_nsr:
1564 vim_account_id = deep_get(db_nsr, ("instantiate_params", "vimAccountId"))
1565 vca_id = VimAccountDB.get_vim_account_with_id(vim_account_id).get("vca")
1566 return vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001567
garciadeblas5697b8b2021-03-24 09:17:02 +01001568 async def instantiate_N2VC(
1569 self,
1570 logging_text,
1571 vca_index,
1572 nsi_id,
1573 db_nsr,
1574 db_vnfr,
1575 vdu_id,
1576 kdu_name,
1577 vdu_index,
1578 config_descriptor,
1579 deploy_params,
1580 base_folder,
1581 nslcmop_id,
1582 stage,
1583 vca_type,
1584 vca_name,
1585 ee_config_descriptor,
1586 ):
tiernod8323042019-08-09 11:32:23 +00001587 nsr_id = db_nsr["_id"]
1588 db_update_entry = "_admin.deployed.VCA.{}.".format(vca_index)
tiernoda6fb102019-11-23 00:36:52 +00001589 vca_deployed_list = db_nsr["_admin"]["deployed"]["VCA"]
tiernod8323042019-08-09 11:32:23 +00001590 vca_deployed = db_nsr["_admin"]["deployed"]["VCA"][vca_index]
tiernob996d942020-07-03 14:52:28 +00001591 osm_config = {"osm": {"ns_id": db_nsr["_id"]}}
quilesj7e13aeb2019-10-08 13:34:55 +02001592 db_dict = {
garciadeblas5697b8b2021-03-24 09:17:02 +01001593 "collection": "nsrs",
1594 "filter": {"_id": nsr_id},
1595 "path": db_update_entry,
quilesj7e13aeb2019-10-08 13:34:55 +02001596 }
tiernod8323042019-08-09 11:32:23 +00001597 step = ""
1598 try:
quilesj3655ae02019-12-12 16:08:35 +00001599
garciadeblas5697b8b2021-03-24 09:17:02 +01001600 element_type = "NS"
quilesj3655ae02019-12-12 16:08:35 +00001601 element_under_configuration = nsr_id
1602
tiernod8323042019-08-09 11:32:23 +00001603 vnfr_id = None
1604 if db_vnfr:
1605 vnfr_id = db_vnfr["_id"]
tiernob996d942020-07-03 14:52:28 +00001606 osm_config["osm"]["vnf_id"] = vnfr_id
tiernod8323042019-08-09 11:32:23 +00001607
garciadeblas5697b8b2021-03-24 09:17:02 +01001608 namespace = "{nsi}.{ns}".format(nsi=nsi_id if nsi_id else "", ns=nsr_id)
quilesj3655ae02019-12-12 16:08:35 +00001609
aktas730569b2021-07-29 17:42:49 +03001610 if vca_type == "native_charm":
1611 index_number = 0
1612 else:
1613 index_number = vdu_index or 0
1614
tiernod8323042019-08-09 11:32:23 +00001615 if vnfr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01001616 element_type = "VNF"
quilesj3655ae02019-12-12 16:08:35 +00001617 element_under_configuration = vnfr_id
aktas730569b2021-07-29 17:42:49 +03001618 namespace += ".{}-{}".format(vnfr_id, index_number)
tiernod8323042019-08-09 11:32:23 +00001619 if vdu_id:
aktas730569b2021-07-29 17:42:49 +03001620 namespace += ".{}-{}".format(vdu_id, index_number)
garciadeblas5697b8b2021-03-24 09:17:02 +01001621 element_type = "VDU"
aktas730569b2021-07-29 17:42:49 +03001622 element_under_configuration = "{}-{}".format(vdu_id, index_number)
tiernob996d942020-07-03 14:52:28 +00001623 osm_config["osm"]["vdu_id"] = vdu_id
tierno51183952020-04-03 15:48:18 +00001624 elif kdu_name:
aktas730569b2021-07-29 17:42:49 +03001625 namespace += ".{}".format(kdu_name)
garciadeblas5697b8b2021-03-24 09:17:02 +01001626 element_type = "KDU"
tierno51183952020-04-03 15:48:18 +00001627 element_under_configuration = kdu_name
tiernob996d942020-07-03 14:52:28 +00001628 osm_config["osm"]["kdu_name"] = kdu_name
tiernod8323042019-08-09 11:32:23 +00001629
1630 # Get artifact path
tierno588547c2020-07-01 15:30:20 +00001631 artifact_path = "{}/{}/{}/{}".format(
tiernod8323042019-08-09 11:32:23 +00001632 base_folder["folder"],
1633 base_folder["pkg-dir"],
garciadeblas5697b8b2021-03-24 09:17:02 +01001634 "charms"
1635 if vca_type in ("native_charm", "lxc_proxy_charm", "k8s_proxy_charm")
1636 else "helm-charts",
1637 vca_name,
tiernod8323042019-08-09 11:32:23 +00001638 )
bravof922c4172020-11-24 21:21:43 -03001639
1640 self.logger.debug("Artifact path > {}".format(artifact_path))
1641
tiernoa278b842020-07-08 15:33:55 +00001642 # get initial_config_primitive_list that applies to this element
garciadeblas5697b8b2021-03-24 09:17:02 +01001643 initial_config_primitive_list = config_descriptor.get(
1644 "initial-config-primitive"
1645 )
tiernoa278b842020-07-08 15:33:55 +00001646
garciadeblas5697b8b2021-03-24 09:17:02 +01001647 self.logger.debug(
1648 "Initial config primitive list > {}".format(
1649 initial_config_primitive_list
1650 )
1651 )
bravof922c4172020-11-24 21:21:43 -03001652
tiernoa278b842020-07-08 15:33:55 +00001653 # add config if not present for NS charm
1654 ee_descriptor_id = ee_config_descriptor.get("id")
bravof922c4172020-11-24 21:21:43 -03001655 self.logger.debug("EE Descriptor > {}".format(ee_descriptor_id))
garciadeblas5697b8b2021-03-24 09:17:02 +01001656 initial_config_primitive_list = get_ee_sorted_initial_config_primitive_list(
1657 initial_config_primitive_list, vca_deployed, ee_descriptor_id
1658 )
tiernod8323042019-08-09 11:32:23 +00001659
garciadeblas5697b8b2021-03-24 09:17:02 +01001660 self.logger.debug(
1661 "Initial config primitive list #2 > {}".format(
1662 initial_config_primitive_list
1663 )
1664 )
tierno588547c2020-07-01 15:30:20 +00001665 # n2vc_redesign STEP 3.1
tierno588547c2020-07-01 15:30:20 +00001666 # find old ee_id if exists
1667 ee_id = vca_deployed.get("ee_id")
tiernod8323042019-08-09 11:32:23 +00001668
David Garciac1fe90a2021-03-31 19:12:02 +02001669 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno588547c2020-07-01 15:30:20 +00001670 # create or register execution environment in VCA
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001671 if vca_type in ("lxc_proxy_charm", "k8s_proxy_charm", "helm", "helm-v3"):
quilesj7e13aeb2019-10-08 13:34:55 +02001672
tierno588547c2020-07-01 15:30:20 +00001673 self._write_configuration_status(
1674 nsr_id=nsr_id,
1675 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001676 status="CREATING",
tierno588547c2020-07-01 15:30:20 +00001677 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001678 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001679 )
tiernod8323042019-08-09 11:32:23 +00001680
tierno588547c2020-07-01 15:30:20 +00001681 step = "create execution environment"
garciadeblas5697b8b2021-03-24 09:17:02 +01001682 self.logger.debug(logging_text + step)
David Garciaaae391f2020-11-09 11:12:54 +01001683
1684 ee_id = None
1685 credentials = None
1686 if vca_type == "k8s_proxy_charm":
1687 ee_id = await self.vca_map[vca_type].install_k8s_proxy_charm(
garciadeblas5697b8b2021-03-24 09:17:02 +01001688 charm_name=artifact_path[artifact_path.rfind("/") + 1 :],
David Garciaaae391f2020-11-09 11:12:54 +01001689 namespace=namespace,
1690 artifact_path=artifact_path,
1691 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001692 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001693 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001694 elif vca_type == "helm" or vca_type == "helm-v3":
1695 ee_id, credentials = await self.vca_map[
1696 vca_type
1697 ].create_execution_environment(
bravof922c4172020-11-24 21:21:43 -03001698 namespace=namespace,
1699 reuse_ee_id=ee_id,
1700 db_dict=db_dict,
lloretgalleg18cb3cb2020-12-10 14:21:10 +00001701 config=osm_config,
1702 artifact_path=artifact_path,
garciadeblas5697b8b2021-03-24 09:17:02 +01001703 vca_type=vca_type,
bravof922c4172020-11-24 21:21:43 -03001704 )
garciadeblas5697b8b2021-03-24 09:17:02 +01001705 else:
1706 ee_id, credentials = await self.vca_map[
1707 vca_type
1708 ].create_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001709 namespace=namespace,
1710 reuse_ee_id=ee_id,
1711 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001712 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001713 )
quilesj3655ae02019-12-12 16:08:35 +00001714
tierno588547c2020-07-01 15:30:20 +00001715 elif vca_type == "native_charm":
1716 step = "Waiting to VM being up and getting IP address"
1717 self.logger.debug(logging_text + step)
garciadeblas5697b8b2021-03-24 09:17:02 +01001718 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1719 logging_text,
1720 nsr_id,
1721 vnfr_id,
1722 vdu_id,
1723 vdu_index,
1724 user=None,
1725 pub_key=None,
1726 )
tierno588547c2020-07-01 15:30:20 +00001727 credentials = {"hostname": rw_mgmt_ip}
1728 # get username
garciadeblas5697b8b2021-03-24 09:17:02 +01001729 username = deep_get(
1730 config_descriptor, ("config-access", "ssh-access", "default-user")
1731 )
tierno588547c2020-07-01 15:30:20 +00001732 # TODO remove this when changes on IM regarding config-access:ssh-access:default-user were
1733 # merged. Meanwhile let's get username from initial-config-primitive
tiernoa278b842020-07-08 15:33:55 +00001734 if not username and initial_config_primitive_list:
1735 for config_primitive in initial_config_primitive_list:
tierno588547c2020-07-01 15:30:20 +00001736 for param in config_primitive.get("parameter", ()):
1737 if param["name"] == "ssh-username":
1738 username = param["value"]
1739 break
1740 if not username:
garciadeblas5697b8b2021-03-24 09:17:02 +01001741 raise LcmException(
1742 "Cannot determine the username neither with 'initial-config-primitive' nor with "
1743 "'config-access.ssh-access.default-user'"
1744 )
tierno588547c2020-07-01 15:30:20 +00001745 credentials["username"] = username
1746 # n2vc_redesign STEP 3.2
quilesj3655ae02019-12-12 16:08:35 +00001747
tierno588547c2020-07-01 15:30:20 +00001748 self._write_configuration_status(
1749 nsr_id=nsr_id,
1750 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001751 status="REGISTERING",
tierno588547c2020-07-01 15:30:20 +00001752 element_under_configuration=element_under_configuration,
garciadeblas5697b8b2021-03-24 09:17:02 +01001753 element_type=element_type,
tierno588547c2020-07-01 15:30:20 +00001754 )
quilesj3655ae02019-12-12 16:08:35 +00001755
tierno588547c2020-07-01 15:30:20 +00001756 step = "register execution environment {}".format(credentials)
1757 self.logger.debug(logging_text + step)
1758 ee_id = await self.vca_map[vca_type].register_execution_environment(
David Garciaaae391f2020-11-09 11:12:54 +01001759 credentials=credentials,
1760 namespace=namespace,
1761 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02001762 vca_id=vca_id,
David Garciaaae391f2020-11-09 11:12:54 +01001763 )
tierno3bedc9b2019-11-27 15:46:57 +00001764
tierno588547c2020-07-01 15:30:20 +00001765 # for compatibility with MON/POL modules, the need model and application name at database
1766 # TODO ask MON/POL if needed to not assuming anymore the format "model_name.application_name"
garciadeblas5697b8b2021-03-24 09:17:02 +01001767 ee_id_parts = ee_id.split(".")
tierno588547c2020-07-01 15:30:20 +00001768 db_nsr_update = {db_update_entry + "ee_id": ee_id}
1769 if len(ee_id_parts) >= 2:
1770 model_name = ee_id_parts[0]
1771 application_name = ee_id_parts[1]
1772 db_nsr_update[db_update_entry + "model"] = model_name
1773 db_nsr_update[db_update_entry + "application"] = application_name
tiernod8323042019-08-09 11:32:23 +00001774
1775 # n2vc_redesign STEP 3.3
tiernod8323042019-08-09 11:32:23 +00001776 step = "Install configuration Software"
quilesj3655ae02019-12-12 16:08:35 +00001777
tiernoc231a872020-01-21 08:49:05 +00001778 self._write_configuration_status(
quilesj3655ae02019-12-12 16:08:35 +00001779 nsr_id=nsr_id,
1780 vca_index=vca_index,
garciadeblas5697b8b2021-03-24 09:17:02 +01001781 status="INSTALLING SW",
quilesj3655ae02019-12-12 16:08:35 +00001782 element_under_configuration=element_under_configuration,
tierno51183952020-04-03 15:48:18 +00001783 element_type=element_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01001784 other_update=db_nsr_update,
quilesj3655ae02019-12-12 16:08:35 +00001785 )
1786
tierno3bedc9b2019-11-27 15:46:57 +00001787 # TODO check if already done
quilesj7e13aeb2019-10-08 13:34:55 +02001788 self.logger.debug(logging_text + step)
David Garcia18a63322020-04-01 16:14:59 +02001789 config = None
tierno588547c2020-07-01 15:30:20 +00001790 if vca_type == "native_charm":
garciadeblas5697b8b2021-03-24 09:17:02 +01001791 config_primitive = next(
1792 (p for p in initial_config_primitive_list if p["name"] == "config"),
1793 None,
1794 )
tiernoa278b842020-07-08 15:33:55 +00001795 if config_primitive:
1796 config = self._map_primitive_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01001797 config_primitive, {}, deploy_params
tiernoa278b842020-07-08 15:33:55 +00001798 )
tierno588547c2020-07-01 15:30:20 +00001799 num_units = 1
1800 if vca_type == "lxc_proxy_charm":
1801 if element_type == "NS":
1802 num_units = db_nsr.get("config-units") or 1
1803 elif element_type == "VNF":
1804 num_units = db_vnfr.get("config-units") or 1
1805 elif element_type == "VDU":
1806 for v in db_vnfr["vdur"]:
1807 if vdu_id == v["vdu-id-ref"]:
1808 num_units = v.get("config-units") or 1
1809 break
David Garciaaae391f2020-11-09 11:12:54 +01001810 if vca_type != "k8s_proxy_charm":
1811 await self.vca_map[vca_type].install_configuration_sw(
1812 ee_id=ee_id,
1813 artifact_path=artifact_path,
1814 db_dict=db_dict,
1815 config=config,
1816 num_units=num_units,
David Garciac1fe90a2021-03-31 19:12:02 +02001817 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001818 vca_type=vca_type,
David Garciaaae391f2020-11-09 11:12:54 +01001819 )
quilesj7e13aeb2019-10-08 13:34:55 +02001820
quilesj63f90042020-01-17 09:53:55 +00001821 # write in db flag of configuration_sw already installed
garciadeblas5697b8b2021-03-24 09:17:02 +01001822 self.update_db_2(
1823 "nsrs", nsr_id, {db_update_entry + "config_sw_installed": True}
1824 )
quilesj63f90042020-01-17 09:53:55 +00001825
1826 # add relations for this VCA (wait for other peers related with this VCA)
garciadeblas5697b8b2021-03-24 09:17:02 +01001827 await self._add_vca_relations(
1828 logging_text=logging_text,
1829 nsr_id=nsr_id,
1830 vca_index=vca_index,
1831 vca_id=vca_id,
1832 vca_type=vca_type,
1833 )
quilesj63f90042020-01-17 09:53:55 +00001834
quilesj7e13aeb2019-10-08 13:34:55 +02001835 # if SSH access is required, then get execution environment SSH public
David Garciaa27e20a2020-07-10 13:12:44 +02001836 # if native charm we have waited already to VM be UP
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001837 if vca_type in ("k8s_proxy_charm", "lxc_proxy_charm", "helm", "helm-v3"):
tierno3bedc9b2019-11-27 15:46:57 +00001838 pub_key = None
1839 user = None
tierno588547c2020-07-01 15:30:20 +00001840 # self.logger.debug("get ssh key block")
garciadeblas5697b8b2021-03-24 09:17:02 +01001841 if deep_get(
1842 config_descriptor, ("config-access", "ssh-access", "required")
1843 ):
tierno588547c2020-07-01 15:30:20 +00001844 # self.logger.debug("ssh key needed")
tierno3bedc9b2019-11-27 15:46:57 +00001845 # Needed to inject a ssh key
garciadeblas5697b8b2021-03-24 09:17:02 +01001846 user = deep_get(
1847 config_descriptor,
1848 ("config-access", "ssh-access", "default-user"),
1849 )
tierno3bedc9b2019-11-27 15:46:57 +00001850 step = "Install configuration Software, getting public ssh key"
David Garciac1fe90a2021-03-31 19:12:02 +02001851 pub_key = await self.vca_map[vca_type].get_ee_ssh_public__key(
garciadeblas5697b8b2021-03-24 09:17:02 +01001852 ee_id=ee_id, db_dict=db_dict, vca_id=vca_id
David Garciac1fe90a2021-03-31 19:12:02 +02001853 )
quilesj7e13aeb2019-10-08 13:34:55 +02001854
garciadeblas5697b8b2021-03-24 09:17:02 +01001855 step = "Insert public key into VM user={} ssh_key={}".format(
1856 user, pub_key
1857 )
tierno3bedc9b2019-11-27 15:46:57 +00001858 else:
tierno588547c2020-07-01 15:30:20 +00001859 # self.logger.debug("no need to get ssh key")
tierno3bedc9b2019-11-27 15:46:57 +00001860 step = "Waiting to VM being up and getting IP address"
1861 self.logger.debug(logging_text + step)
quilesj7e13aeb2019-10-08 13:34:55 +02001862
tierno3bedc9b2019-11-27 15:46:57 +00001863 # n2vc_redesign STEP 5.1
1864 # wait for RO (ip-address) Insert pub_key into VM
tierno5ee02052019-12-05 19:55:02 +00001865 if vnfr_id:
tierno7ecbc342020-09-21 14:05:39 +00001866 if kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01001867 rw_mgmt_ip = await self.wait_kdu_up(
1868 logging_text, nsr_id, vnfr_id, kdu_name
1869 )
tierno7ecbc342020-09-21 14:05:39 +00001870 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001871 rw_mgmt_ip = await self.wait_vm_up_insert_key_ro(
1872 logging_text,
1873 nsr_id,
1874 vnfr_id,
1875 vdu_id,
1876 vdu_index,
1877 user=user,
1878 pub_key=pub_key,
1879 )
tierno5ee02052019-12-05 19:55:02 +00001880 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01001881 rw_mgmt_ip = None # This is for a NS configuration
tierno3bedc9b2019-11-27 15:46:57 +00001882
garciadeblas5697b8b2021-03-24 09:17:02 +01001883 self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip))
quilesj7e13aeb2019-10-08 13:34:55 +02001884
tiernoa5088192019-11-26 16:12:53 +00001885 # store rw_mgmt_ip in deploy params for later replacement
quilesj7e13aeb2019-10-08 13:34:55 +02001886 deploy_params["rw_mgmt_ip"] = rw_mgmt_ip
tiernod8323042019-08-09 11:32:23 +00001887
1888 # n2vc_redesign STEP 6 Execute initial config primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01001889 step = "execute initial config primitive"
quilesj3655ae02019-12-12 16:08:35 +00001890
1891 # wait for dependent primitives execution (NS -> VNF -> VDU)
tierno5ee02052019-12-05 19:55:02 +00001892 if initial_config_primitive_list:
1893 await self._wait_dependent_n2vc(nsr_id, vca_deployed_list, vca_index)
quilesj3655ae02019-12-12 16:08:35 +00001894
1895 # stage, in function of element type: vdu, kdu, vnf or ns
1896 my_vca = vca_deployed_list[vca_index]
1897 if my_vca.get("vdu_id") or my_vca.get("kdu_name"):
1898 # VDU or KDU
garciadeblas5697b8b2021-03-24 09:17:02 +01001899 stage[0] = "Stage 3/5: running Day-1 primitives for VDU."
quilesj3655ae02019-12-12 16:08:35 +00001900 elif my_vca.get("member-vnf-index"):
1901 # VNF
garciadeblas5697b8b2021-03-24 09:17:02 +01001902 stage[0] = "Stage 4/5: running Day-1 primitives for VNF."
quilesj3655ae02019-12-12 16:08:35 +00001903 else:
1904 # NS
garciadeblas5697b8b2021-03-24 09:17:02 +01001905 stage[0] = "Stage 5/5: running Day-1 primitives for NS."
quilesj3655ae02019-12-12 16:08:35 +00001906
tiernoc231a872020-01-21 08:49:05 +00001907 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001908 nsr_id=nsr_id, vca_index=vca_index, status="EXECUTING PRIMITIVE"
quilesj3655ae02019-12-12 16:08:35 +00001909 )
1910
garciadeblas5697b8b2021-03-24 09:17:02 +01001911 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00001912
tiernoe876f672020-02-13 14:34:48 +00001913 check_if_terminated_needed = True
tiernod8323042019-08-09 11:32:23 +00001914 for initial_config_primitive in initial_config_primitive_list:
tiernoda6fb102019-11-23 00:36:52 +00001915 # adding information on the vca_deployed if it is a NS execution environment
1916 if not vca_deployed["member-vnf-index"]:
garciadeblas5697b8b2021-03-24 09:17:02 +01001917 deploy_params["ns_config_info"] = json.dumps(
1918 self._get_ns_config_info(nsr_id)
1919 )
tiernod8323042019-08-09 11:32:23 +00001920 # TODO check if already done
garciadeblas5697b8b2021-03-24 09:17:02 +01001921 primitive_params_ = self._map_primitive_params(
1922 initial_config_primitive, {}, deploy_params
1923 )
tierno3bedc9b2019-11-27 15:46:57 +00001924
garciadeblas5697b8b2021-03-24 09:17:02 +01001925 step = "execute primitive '{}' params '{}'".format(
1926 initial_config_primitive["name"], primitive_params_
1927 )
tiernod8323042019-08-09 11:32:23 +00001928 self.logger.debug(logging_text + step)
tierno588547c2020-07-01 15:30:20 +00001929 await self.vca_map[vca_type].exec_primitive(
quilesj7e13aeb2019-10-08 13:34:55 +02001930 ee_id=ee_id,
1931 primitive_name=initial_config_primitive["name"],
1932 params_dict=primitive_params_,
David Garciac1fe90a2021-03-31 19:12:02 +02001933 db_dict=db_dict,
1934 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03001935 vca_type=vca_type,
quilesj7e13aeb2019-10-08 13:34:55 +02001936 )
tiernoe876f672020-02-13 14:34:48 +00001937 # Once some primitive has been exec, check and write at db if it needs to exec terminated primitives
1938 if check_if_terminated_needed:
garciadeblas5697b8b2021-03-24 09:17:02 +01001939 if config_descriptor.get("terminate-config-primitive"):
1940 self.update_db_2(
1941 "nsrs", nsr_id, {db_update_entry + "needed_terminate": True}
1942 )
tiernoe876f672020-02-13 14:34:48 +00001943 check_if_terminated_needed = False
quilesj3655ae02019-12-12 16:08:35 +00001944
tiernod8323042019-08-09 11:32:23 +00001945 # TODO register in database that primitive is done
quilesj7e13aeb2019-10-08 13:34:55 +02001946
tiernob996d942020-07-03 14:52:28 +00001947 # STEP 7 Configure metrics
lloretgalleg18ebc3a2020-10-22 09:54:51 +00001948 if vca_type == "helm" or vca_type == "helm-v3":
tiernob996d942020-07-03 14:52:28 +00001949 prometheus_jobs = await self.add_prometheus_metrics(
1950 ee_id=ee_id,
1951 artifact_path=artifact_path,
1952 ee_config_descriptor=ee_config_descriptor,
1953 vnfr_id=vnfr_id,
1954 nsr_id=nsr_id,
1955 target_ip=rw_mgmt_ip,
1956 )
1957 if prometheus_jobs:
garciadeblas5697b8b2021-03-24 09:17:02 +01001958 self.update_db_2(
1959 "nsrs",
1960 nsr_id,
1961 {db_update_entry + "prometheus_jobs": prometheus_jobs},
1962 )
tiernob996d942020-07-03 14:52:28 +00001963
quilesj7e13aeb2019-10-08 13:34:55 +02001964 step = "instantiated at VCA"
1965 self.logger.debug(logging_text + step)
1966
tiernoc231a872020-01-21 08:49:05 +00001967 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001968 nsr_id=nsr_id, vca_index=vca_index, status="READY"
quilesj3655ae02019-12-12 16:08:35 +00001969 )
1970
tiernod8323042019-08-09 11:32:23 +00001971 except Exception as e: # TODO not use Exception but N2VC exception
quilesj3655ae02019-12-12 16:08:35 +00001972 # self.update_db_2("nsrs", nsr_id, {db_update_entry + "instantiation": "FAILED"})
garciadeblas5697b8b2021-03-24 09:17:02 +01001973 if not isinstance(
1974 e, (DbException, N2VCException, LcmException, asyncio.CancelledError)
1975 ):
1976 self.logger.error(
1977 "Exception while {} : {}".format(step, e), exc_info=True
1978 )
tiernoc231a872020-01-21 08:49:05 +00001979 self._write_configuration_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01001980 nsr_id=nsr_id, vca_index=vca_index, status="BROKEN"
quilesj3655ae02019-12-12 16:08:35 +00001981 )
tiernoe876f672020-02-13 14:34:48 +00001982 raise LcmException("{} {}".format(step, e)) from e
tiernod8323042019-08-09 11:32:23 +00001983
garciadeblas5697b8b2021-03-24 09:17:02 +01001984 def _write_ns_status(
1985 self,
1986 nsr_id: str,
1987 ns_state: str,
1988 current_operation: str,
1989 current_operation_id: str,
1990 error_description: str = None,
1991 error_detail: str = None,
1992 other_update: dict = None,
1993 ):
tiernoe876f672020-02-13 14:34:48 +00001994 """
1995 Update db_nsr fields.
1996 :param nsr_id:
1997 :param ns_state:
1998 :param current_operation:
1999 :param current_operation_id:
2000 :param error_description:
tiernoa2143262020-03-27 16:20:40 +00002001 :param error_detail:
tiernoe876f672020-02-13 14:34:48 +00002002 :param other_update: Other required changes at database if provided, will be cleared
2003 :return:
2004 """
quilesj4cda56b2019-12-05 10:02:20 +00002005 try:
tiernoe876f672020-02-13 14:34:48 +00002006 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002007 db_dict[
2008 "_admin.nslcmop"
2009 ] = current_operation_id # for backward compatibility
tiernoe876f672020-02-13 14:34:48 +00002010 db_dict["_admin.current-operation"] = current_operation_id
garciadeblas5697b8b2021-03-24 09:17:02 +01002011 db_dict["_admin.operation-type"] = (
2012 current_operation if current_operation != "IDLE" else None
2013 )
quilesj4cda56b2019-12-05 10:02:20 +00002014 db_dict["currentOperation"] = current_operation
2015 db_dict["currentOperationID"] = current_operation_id
2016 db_dict["errorDescription"] = error_description
tiernoa2143262020-03-27 16:20:40 +00002017 db_dict["errorDetail"] = error_detail
tiernoe876f672020-02-13 14:34:48 +00002018
2019 if ns_state:
2020 db_dict["nsState"] = ns_state
quilesj4cda56b2019-12-05 10:02:20 +00002021 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002022 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002023 self.logger.warn("Error writing NS status, ns={}: {}".format(nsr_id, e))
quilesj3655ae02019-12-12 16:08:35 +00002024
garciadeblas5697b8b2021-03-24 09:17:02 +01002025 def _write_op_status(
2026 self,
2027 op_id: str,
2028 stage: list = None,
2029 error_message: str = None,
2030 queuePosition: int = 0,
2031 operation_state: str = None,
2032 other_update: dict = None,
2033 ):
quilesj3655ae02019-12-12 16:08:35 +00002034 try:
tiernoe876f672020-02-13 14:34:48 +00002035 db_dict = other_update or {}
garciadeblas5697b8b2021-03-24 09:17:02 +01002036 db_dict["queuePosition"] = queuePosition
tiernoe876f672020-02-13 14:34:48 +00002037 if isinstance(stage, list):
garciadeblas5697b8b2021-03-24 09:17:02 +01002038 db_dict["stage"] = stage[0]
2039 db_dict["detailed-status"] = " ".join(stage)
tiernoe876f672020-02-13 14:34:48 +00002040 elif stage is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002041 db_dict["stage"] = str(stage)
tiernoe876f672020-02-13 14:34:48 +00002042
2043 if error_message is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002044 db_dict["errorMessage"] = error_message
tiernoe876f672020-02-13 14:34:48 +00002045 if operation_state is not None:
garciadeblas5697b8b2021-03-24 09:17:02 +01002046 db_dict["operationState"] = operation_state
tiernoe876f672020-02-13 14:34:48 +00002047 db_dict["statusEnteredTime"] = time()
quilesj3655ae02019-12-12 16:08:35 +00002048 self.update_db_2("nslcmops", op_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002049 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002050 self.logger.warn(
2051 "Error writing OPERATION status for op_id: {} -> {}".format(op_id, e)
2052 )
quilesj3655ae02019-12-12 16:08:35 +00002053
tierno51183952020-04-03 15:48:18 +00002054 def _write_all_config_status(self, db_nsr: dict, status: str):
quilesj3655ae02019-12-12 16:08:35 +00002055 try:
tierno51183952020-04-03 15:48:18 +00002056 nsr_id = db_nsr["_id"]
quilesj3655ae02019-12-12 16:08:35 +00002057 # configurationStatus
garciadeblas5697b8b2021-03-24 09:17:02 +01002058 config_status = db_nsr.get("configurationStatus")
quilesj3655ae02019-12-12 16:08:35 +00002059 if config_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002060 db_nsr_update = {
2061 "configurationStatus.{}.status".format(index): status
2062 for index, v in enumerate(config_status)
2063 if v
2064 }
quilesj3655ae02019-12-12 16:08:35 +00002065 # update status
tierno51183952020-04-03 15:48:18 +00002066 self.update_db_2("nsrs", nsr_id, db_nsr_update)
quilesj3655ae02019-12-12 16:08:35 +00002067
tiernoe876f672020-02-13 14:34:48 +00002068 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002069 self.logger.warn(
2070 "Error writing all configuration status, ns={}: {}".format(nsr_id, e)
2071 )
quilesj3655ae02019-12-12 16:08:35 +00002072
garciadeblas5697b8b2021-03-24 09:17:02 +01002073 def _write_configuration_status(
2074 self,
2075 nsr_id: str,
2076 vca_index: int,
2077 status: str = None,
2078 element_under_configuration: str = None,
2079 element_type: str = None,
2080 other_update: dict = None,
2081 ):
quilesj3655ae02019-12-12 16:08:35 +00002082
2083 # self.logger.debug('_write_configuration_status(): vca_index={}, status={}'
2084 # .format(vca_index, status))
2085
2086 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002087 db_path = "configurationStatus.{}.".format(vca_index)
tierno51183952020-04-03 15:48:18 +00002088 db_dict = other_update or {}
quilesj63f90042020-01-17 09:53:55 +00002089 if status:
garciadeblas5697b8b2021-03-24 09:17:02 +01002090 db_dict[db_path + "status"] = status
quilesj3655ae02019-12-12 16:08:35 +00002091 if element_under_configuration:
garciadeblas5697b8b2021-03-24 09:17:02 +01002092 db_dict[
2093 db_path + "elementUnderConfiguration"
2094 ] = element_under_configuration
quilesj3655ae02019-12-12 16:08:35 +00002095 if element_type:
garciadeblas5697b8b2021-03-24 09:17:02 +01002096 db_dict[db_path + "elementType"] = element_type
quilesj3655ae02019-12-12 16:08:35 +00002097 self.update_db_2("nsrs", nsr_id, db_dict)
tiernoe876f672020-02-13 14:34:48 +00002098 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002099 self.logger.warn(
2100 "Error writing configuration status={}, ns={}, vca_index={}: {}".format(
2101 status, nsr_id, vca_index, e
2102 )
2103 )
quilesj4cda56b2019-12-05 10:02:20 +00002104
tierno38089af2020-04-16 07:56:58 +00002105 async def _do_placement(self, logging_text, db_nslcmop, db_vnfrs):
2106 """
2107 Check and computes the placement, (vim account where to deploy). If it is decided by an external tool, it
2108 sends the request via kafka and wait until the result is wrote at database (nslcmops _admin.plca).
2109 Database is used because the result can be obtained from a different LCM worker in case of HA.
2110 :param logging_text: contains the prefix for logging, with the ns and nslcmop identifiers
2111 :param db_nslcmop: database content of nslcmop
2112 :param db_vnfrs: database content of vnfrs, indexed by member-vnf-index.
tierno8790a3d2020-04-23 22:49:52 +00002113 :return: True if some modification is done. Modifies database vnfrs and parameter db_vnfr with the
2114 computed 'vim-account-id'
tierno38089af2020-04-16 07:56:58 +00002115 """
tierno8790a3d2020-04-23 22:49:52 +00002116 modified = False
garciadeblas5697b8b2021-03-24 09:17:02 +01002117 nslcmop_id = db_nslcmop["_id"]
2118 placement_engine = deep_get(db_nslcmop, ("operationParams", "placement-engine"))
magnussonle9198bb2020-01-21 13:00:51 +01002119 if placement_engine == "PLA":
garciadeblas5697b8b2021-03-24 09:17:02 +01002120 self.logger.debug(
2121 logging_text + "Invoke and wait for placement optimization"
2122 )
2123 await self.msg.aiowrite(
2124 "pla", "get_placement", {"nslcmopId": nslcmop_id}, loop=self.loop
2125 )
magnussonle9198bb2020-01-21 13:00:51 +01002126 db_poll_interval = 5
tierno38089af2020-04-16 07:56:58 +00002127 wait = db_poll_interval * 10
magnussonle9198bb2020-01-21 13:00:51 +01002128 pla_result = None
2129 while not pla_result and wait >= 0:
2130 await asyncio.sleep(db_poll_interval)
2131 wait -= db_poll_interval
tierno38089af2020-04-16 07:56:58 +00002132 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01002133 pla_result = deep_get(db_nslcmop, ("_admin", "pla"))
magnussonle9198bb2020-01-21 13:00:51 +01002134
2135 if not pla_result:
garciadeblas5697b8b2021-03-24 09:17:02 +01002136 raise LcmException(
2137 "Placement timeout for nslcmopId={}".format(nslcmop_id)
2138 )
magnussonle9198bb2020-01-21 13:00:51 +01002139
garciadeblas5697b8b2021-03-24 09:17:02 +01002140 for pla_vnf in pla_result["vnf"]:
2141 vnfr = db_vnfrs.get(pla_vnf["member-vnf-index"])
2142 if not pla_vnf.get("vimAccountId") or not vnfr:
magnussonle9198bb2020-01-21 13:00:51 +01002143 continue
tierno8790a3d2020-04-23 22:49:52 +00002144 modified = True
garciadeblas5697b8b2021-03-24 09:17:02 +01002145 self.db.set_one(
2146 "vnfrs",
2147 {"_id": vnfr["_id"]},
2148 {"vim-account-id": pla_vnf["vimAccountId"]},
2149 )
tierno38089af2020-04-16 07:56:58 +00002150 # Modifies db_vnfrs
garciadeblas5697b8b2021-03-24 09:17:02 +01002151 vnfr["vim-account-id"] = pla_vnf["vimAccountId"]
tierno8790a3d2020-04-23 22:49:52 +00002152 return modified
magnussonle9198bb2020-01-21 13:00:51 +01002153
2154 def update_nsrs_with_pla_result(self, params):
2155 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002156 nslcmop_id = deep_get(params, ("placement", "nslcmopId"))
2157 self.update_db_2(
2158 "nslcmops", nslcmop_id, {"_admin.pla": params.get("placement")}
2159 )
magnussonle9198bb2020-01-21 13:00:51 +01002160 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002161 self.logger.warn("Update failed for nslcmop_id={}:{}".format(nslcmop_id, e))
magnussonle9198bb2020-01-21 13:00:51 +01002162
tierno59d22d22018-09-25 18:10:19 +02002163 async def instantiate(self, nsr_id, nslcmop_id):
quilesj7e13aeb2019-10-08 13:34:55 +02002164 """
2165
2166 :param nsr_id: ns instance to deploy
2167 :param nslcmop_id: operation to run
2168 :return:
2169 """
kuused124bfe2019-06-18 12:09:24 +02002170
2171 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01002172 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002173 if not task_is_locked_by_me:
garciadeblas5697b8b2021-03-24 09:17:02 +01002174 self.logger.debug(
2175 "instantiate() task is not locked by me, ns={}".format(nsr_id)
2176 )
kuused124bfe2019-06-18 12:09:24 +02002177 return
2178
tierno59d22d22018-09-25 18:10:19 +02002179 logging_text = "Task ns={} instantiate={} ".format(nsr_id, nslcmop_id)
2180 self.logger.debug(logging_text + "Enter")
quilesj7e13aeb2019-10-08 13:34:55 +02002181
tierno59d22d22018-09-25 18:10:19 +02002182 # get all needed from database
quilesj7e13aeb2019-10-08 13:34:55 +02002183
2184 # database nsrs record
tierno59d22d22018-09-25 18:10:19 +02002185 db_nsr = None
quilesj7e13aeb2019-10-08 13:34:55 +02002186
2187 # database nslcmops record
tierno59d22d22018-09-25 18:10:19 +02002188 db_nslcmop = None
quilesj7e13aeb2019-10-08 13:34:55 +02002189
2190 # update operation on nsrs
tiernoe876f672020-02-13 14:34:48 +00002191 db_nsr_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002192 # update operation on nslcmops
tierno59d22d22018-09-25 18:10:19 +02002193 db_nslcmop_update = {}
quilesj7e13aeb2019-10-08 13:34:55 +02002194
tierno59d22d22018-09-25 18:10:19 +02002195 nslcmop_operation_state = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002196 db_vnfrs = {} # vnf's info indexed by member-index
quilesj7e13aeb2019-10-08 13:34:55 +02002197 # n2vc_info = {}
tiernoe876f672020-02-13 14:34:48 +00002198 tasks_dict_info = {} # from task to info text
tierno59d22d22018-09-25 18:10:19 +02002199 exc = None
tiernoe876f672020-02-13 14:34:48 +00002200 error_list = []
garciadeblas5697b8b2021-03-24 09:17:02 +01002201 stage = [
2202 "Stage 1/5: preparation of the environment.",
2203 "Waiting for previous operations to terminate.",
2204 "",
2205 ]
tiernoe876f672020-02-13 14:34:48 +00002206 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02002207 try:
kuused124bfe2019-06-18 12:09:24 +02002208 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01002209 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02002210
quilesj7e13aeb2019-10-08 13:34:55 +02002211 # STEP 0: Reading database (nslcmops, nsrs, nsds, vnfrs, vnfds)
tiernob5203912020-08-11 11:20:13 +00002212 stage[1] = "Reading from database."
quilesj4cda56b2019-12-05 10:02:20 +00002213 # nsState="BUILDING", currentOperation="INSTANTIATING", currentOperationID=nslcmop_id
tiernoe876f672020-02-13 14:34:48 +00002214 db_nsr_update["detailed-status"] = "creating"
2215 db_nsr_update["operational-status"] = "init"
quilesj4cda56b2019-12-05 10:02:20 +00002216 self._write_ns_status(
2217 nsr_id=nsr_id,
2218 ns_state="BUILDING",
2219 current_operation="INSTANTIATING",
tiernoe876f672020-02-13 14:34:48 +00002220 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01002221 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002222 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002223 self._write_op_status(op_id=nslcmop_id, stage=stage, queuePosition=0)
quilesj4cda56b2019-12-05 10:02:20 +00002224
quilesj7e13aeb2019-10-08 13:34:55 +02002225 # read from db: operation
tiernob5203912020-08-11 11:20:13 +00002226 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
tierno59d22d22018-09-25 18:10:19 +02002227 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002228 if db_nslcmop["operationParams"].get("additionalParamsForVnf"):
2229 db_nslcmop["operationParams"]["additionalParamsForVnf"] = json.loads(
2230 db_nslcmop["operationParams"]["additionalParamsForVnf"]
2231 )
tierno744303e2020-01-13 16:46:31 +00002232 ns_params = db_nslcmop.get("operationParams")
2233 if ns_params and ns_params.get("timeout_ns_deploy"):
2234 timeout_ns_deploy = ns_params["timeout_ns_deploy"]
2235 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002236 timeout_ns_deploy = self.timeout.get(
2237 "ns_deploy", self.timeout_ns_deploy
2238 )
quilesj7e13aeb2019-10-08 13:34:55 +02002239
2240 # read from db: ns
tiernob5203912020-08-11 11:20:13 +00002241 stage[1] = "Getting nsr={} from db.".format(nsr_id)
tierno59d22d22018-09-25 18:10:19 +02002242 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
tiernob5203912020-08-11 11:20:13 +00002243 stage[1] = "Getting nsd={} from db.".format(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002244 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
bravof021e70d2021-03-11 12:03:30 -03002245 self.fs.sync(db_nsr["nsd-id"])
tiernod732fb82020-05-21 13:18:23 +00002246 db_nsr["nsd"] = nsd
tiernod8323042019-08-09 11:32:23 +00002247 # nsr_name = db_nsr["name"] # TODO short-name??
tierno47e86b52018-10-10 14:05:55 +02002248
quilesj7e13aeb2019-10-08 13:34:55 +02002249 # read from db: vnf's of this ns
tiernob5203912020-08-11 11:20:13 +00002250 stage[1] = "Getting vnfrs from db."
tiernoe876f672020-02-13 14:34:48 +00002251 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002252 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
tierno27246d82018-09-27 15:59:09 +02002253
quilesj7e13aeb2019-10-08 13:34:55 +02002254 # read from db: vnfd's for every vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002255 db_vnfds = [] # every vnfd data
quilesj7e13aeb2019-10-08 13:34:55 +02002256
2257 # for each vnf in ns, read vnfd
tierno27246d82018-09-27 15:59:09 +02002258 for vnfr in db_vnfrs_list:
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01002259 if vnfr.get("kdur"):
2260 kdur_list = []
2261 for kdur in vnfr["kdur"]:
2262 if kdur.get("additionalParams"):
2263 kdur["additionalParams"] = json.loads(kdur["additionalParams"])
2264 kdur_list.append(kdur)
2265 vnfr["kdur"] = kdur_list
2266
bravof922c4172020-11-24 21:21:43 -03002267 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
2268 vnfd_id = vnfr["vnfd-id"]
2269 vnfd_ref = vnfr["vnfd-ref"]
bravof021e70d2021-03-11 12:03:30 -03002270 self.fs.sync(vnfd_id)
lloretgalleg6d488782020-07-22 10:13:46 +00002271
quilesj7e13aeb2019-10-08 13:34:55 +02002272 # if we haven't this vnfd, read it from db
tierno27246d82018-09-27 15:59:09 +02002273 if vnfd_id not in db_vnfds:
quilesj63f90042020-01-17 09:53:55 +00002274 # read from db
garciadeblas5697b8b2021-03-24 09:17:02 +01002275 stage[1] = "Getting vnfd={} id='{}' from db.".format(
2276 vnfd_id, vnfd_ref
2277 )
tiernoe876f672020-02-13 14:34:48 +00002278 self.logger.debug(logging_text + stage[1])
tierno27246d82018-09-27 15:59:09 +02002279 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
tierno27246d82018-09-27 15:59:09 +02002280
quilesj7e13aeb2019-10-08 13:34:55 +02002281 # store vnfd
David Garciad41dbd62020-12-10 12:52:52 +01002282 db_vnfds.append(vnfd)
quilesj7e13aeb2019-10-08 13:34:55 +02002283
2284 # Get or generates the _admin.deployed.VCA list
tiernoe4f7e6c2018-11-27 14:55:30 +00002285 vca_deployed_list = None
2286 if db_nsr["_admin"].get("deployed"):
2287 vca_deployed_list = db_nsr["_admin"]["deployed"].get("VCA")
2288 if vca_deployed_list is None:
2289 vca_deployed_list = []
quilesj3655ae02019-12-12 16:08:35 +00002290 configuration_status_list = []
tiernoe4f7e6c2018-11-27 14:55:30 +00002291 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
quilesj3655ae02019-12-12 16:08:35 +00002292 db_nsr_update["configurationStatus"] = configuration_status_list
quilesj7e13aeb2019-10-08 13:34:55 +02002293 # add _admin.deployed.VCA to db_nsr dictionary, value=vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002294 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002295 elif isinstance(vca_deployed_list, dict):
2296 # maintain backward compatibility. Change a dict to list at database
2297 vca_deployed_list = list(vca_deployed_list.values())
2298 db_nsr_update["_admin.deployed.VCA"] = vca_deployed_list
tierno98ad6ea2019-05-30 17:16:28 +00002299 populate_dict(db_nsr, ("_admin", "deployed", "VCA"), vca_deployed_list)
tiernoe4f7e6c2018-11-27 14:55:30 +00002300
garciadeblas5697b8b2021-03-24 09:17:02 +01002301 if not isinstance(
2302 deep_get(db_nsr, ("_admin", "deployed", "RO", "vnfd")), list
2303 ):
tiernoa009e552019-01-30 16:45:44 +00002304 populate_dict(db_nsr, ("_admin", "deployed", "RO", "vnfd"), [])
2305 db_nsr_update["_admin.deployed.RO.vnfd"] = []
tierno59d22d22018-09-25 18:10:19 +02002306
tiernobaa51102018-12-14 13:16:18 +00002307 # set state to INSTANTIATED. When instantiated NBI will not delete directly
2308 db_nsr_update["_admin.nsState"] = "INSTANTIATED"
2309 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01002310 self.db.set_list(
2311 "vnfrs", {"nsr-id-ref": nsr_id}, {"_admin.nsState": "INSTANTIATED"}
2312 )
quilesj3655ae02019-12-12 16:08:35 +00002313
2314 # n2vc_redesign STEP 2 Deploy Network Scenario
garciadeblas5697b8b2021-03-24 09:17:02 +01002315 stage[0] = "Stage 2/5: deployment of KDUs, VMs and execution environments."
2316 self._write_op_status(op_id=nslcmop_id, stage=stage)
quilesj3655ae02019-12-12 16:08:35 +00002317
tiernob5203912020-08-11 11:20:13 +00002318 stage[1] = "Deploying KDUs."
tiernoe876f672020-02-13 14:34:48 +00002319 # self.logger.debug(logging_text + "Before deploy_kdus")
calvinosanch9f9c6f22019-11-04 13:37:39 +01002320 # Call to deploy_kdus in case exists the "vdu:kdu" param
tiernoe876f672020-02-13 14:34:48 +00002321 await self.deploy_kdus(
2322 logging_text=logging_text,
2323 nsr_id=nsr_id,
2324 nslcmop_id=nslcmop_id,
2325 db_vnfrs=db_vnfrs,
2326 db_vnfds=db_vnfds,
2327 task_instantiation_info=tasks_dict_info,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002328 )
tiernoe876f672020-02-13 14:34:48 +00002329
2330 stage[1] = "Getting VCA public key."
tiernod8323042019-08-09 11:32:23 +00002331 # n2vc_redesign STEP 1 Get VCA public ssh-key
2332 # feature 1429. Add n2vc public key to needed VMs
tierno3bedc9b2019-11-27 15:46:57 +00002333 n2vc_key = self.n2vc.get_public_key()
tiernoa5088192019-11-26 16:12:53 +00002334 n2vc_key_list = [n2vc_key]
2335 if self.vca_config.get("public_key"):
2336 n2vc_key_list.append(self.vca_config["public_key"])
tierno98ad6ea2019-05-30 17:16:28 +00002337
tiernoe876f672020-02-13 14:34:48 +00002338 stage[1] = "Deploying NS at VIM."
tiernod8323042019-08-09 11:32:23 +00002339 task_ro = asyncio.ensure_future(
quilesj7e13aeb2019-10-08 13:34:55 +02002340 self.instantiate_RO(
2341 logging_text=logging_text,
2342 nsr_id=nsr_id,
2343 nsd=nsd,
2344 db_nsr=db_nsr,
2345 db_nslcmop=db_nslcmop,
2346 db_vnfrs=db_vnfrs,
bravof922c4172020-11-24 21:21:43 -03002347 db_vnfds=db_vnfds,
tiernoe876f672020-02-13 14:34:48 +00002348 n2vc_key_list=n2vc_key_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002349 stage=stage,
tierno98ad6ea2019-05-30 17:16:28 +00002350 )
tiernod8323042019-08-09 11:32:23 +00002351 )
2352 self.lcm_tasks.register("ns", nsr_id, nslcmop_id, "instantiate_RO", task_ro)
tiernoa2143262020-03-27 16:20:40 +00002353 tasks_dict_info[task_ro] = "Deploying at VIM"
tierno98ad6ea2019-05-30 17:16:28 +00002354
tiernod8323042019-08-09 11:32:23 +00002355 # n2vc_redesign STEP 3 to 6 Deploy N2VC
tiernoe876f672020-02-13 14:34:48 +00002356 stage[1] = "Deploying Execution Environments."
2357 self.logger.debug(logging_text + stage[1])
tierno98ad6ea2019-05-30 17:16:28 +00002358
tiernod8323042019-08-09 11:32:23 +00002359 nsi_id = None # TODO put nsi_id when this nsr belongs to a NSI
bravof922c4172020-11-24 21:21:43 -03002360 for vnf_profile in get_vnf_profiles(nsd):
2361 vnfd_id = vnf_profile["vnfd-id"]
2362 vnfd = find_in_list(db_vnfds, lambda a_vnf: a_vnf["id"] == vnfd_id)
2363 member_vnf_index = str(vnf_profile["id"])
tiernod8323042019-08-09 11:32:23 +00002364 db_vnfr = db_vnfrs[member_vnf_index]
2365 base_folder = vnfd["_admin"]["storage"]
2366 vdu_id = None
2367 vdu_index = 0
tierno98ad6ea2019-05-30 17:16:28 +00002368 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002369 kdu_name = None
tierno59d22d22018-09-25 18:10:19 +02002370
tierno8a518872018-12-21 13:42:14 +00002371 # Get additional parameters
bravof922c4172020-11-24 21:21:43 -03002372 deploy_params = {"OSM": get_osm_params(db_vnfr)}
tiernod8323042019-08-09 11:32:23 +00002373 if db_vnfr.get("additionalParamsForVnf"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002374 deploy_params.update(
2375 parse_yaml_strings(db_vnfr["additionalParamsForVnf"].copy())
2376 )
tierno8a518872018-12-21 13:42:14 +00002377
bravofe5a31bc2021-02-17 19:09:12 -03002378 descriptor_config = get_configuration(vnfd, vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00002379 if descriptor_config:
quilesj7e13aeb2019-10-08 13:34:55 +02002380 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002381 logging_text=logging_text
2382 + "member_vnf_index={} ".format(member_vnf_index),
quilesj7e13aeb2019-10-08 13:34:55 +02002383 db_nsr=db_nsr,
2384 db_vnfr=db_vnfr,
2385 nslcmop_id=nslcmop_id,
2386 nsr_id=nsr_id,
2387 nsi_id=nsi_id,
2388 vnfd_id=vnfd_id,
2389 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002390 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002391 member_vnf_index=member_vnf_index,
2392 vdu_index=vdu_index,
2393 vdu_name=vdu_name,
2394 deploy_params=deploy_params,
2395 descriptor_config=descriptor_config,
2396 base_folder=base_folder,
tiernoe876f672020-02-13 14:34:48 +00002397 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002398 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002399 )
tierno59d22d22018-09-25 18:10:19 +02002400
2401 # Deploy charms for each VDU that supports one.
bravof922c4172020-11-24 21:21:43 -03002402 for vdud in get_vdu_list(vnfd):
tiernod8323042019-08-09 11:32:23 +00002403 vdu_id = vdud["id"]
bravofe5a31bc2021-02-17 19:09:12 -03002404 descriptor_config = get_configuration(vnfd, vdu_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01002405 vdur = find_in_list(
2406 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
2407 )
bravof922c4172020-11-24 21:21:43 -03002408
tierno626e0152019-11-29 14:16:16 +00002409 if vdur.get("additionalParams"):
bravof922c4172020-11-24 21:21:43 -03002410 deploy_params_vdu = parse_yaml_strings(vdur["additionalParams"])
tierno626e0152019-11-29 14:16:16 +00002411 else:
2412 deploy_params_vdu = deploy_params
garciadeblas5697b8b2021-03-24 09:17:02 +01002413 deploy_params_vdu["OSM"] = get_osm_params(
2414 db_vnfr, vdu_id, vdu_count_index=0
2415 )
endika85d73a62021-06-21 18:55:07 +02002416 vdud_count = get_number_of_instances(vnfd, vdu_id)
bravof922c4172020-11-24 21:21:43 -03002417
2418 self.logger.debug("VDUD > {}".format(vdud))
garciadeblas5697b8b2021-03-24 09:17:02 +01002419 self.logger.debug(
2420 "Descriptor config > {}".format(descriptor_config)
2421 )
tierno588547c2020-07-01 15:30:20 +00002422 if descriptor_config:
tiernod8323042019-08-09 11:32:23 +00002423 vdu_name = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002424 kdu_name = None
bravof922c4172020-11-24 21:21:43 -03002425 for vdu_index in range(vdud_count):
tiernod8323042019-08-09 11:32:23 +00002426 # TODO vnfr_params["rw_mgmt_ip"] = vdur["ip-address"]
quilesj7e13aeb2019-10-08 13:34:55 +02002427 self._deploy_n2vc(
garciadeblas5697b8b2021-03-24 09:17:02 +01002428 logging_text=logging_text
2429 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
2430 member_vnf_index, vdu_id, vdu_index
2431 ),
quilesj7e13aeb2019-10-08 13:34:55 +02002432 db_nsr=db_nsr,
2433 db_vnfr=db_vnfr,
2434 nslcmop_id=nslcmop_id,
2435 nsr_id=nsr_id,
2436 nsi_id=nsi_id,
2437 vnfd_id=vnfd_id,
2438 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002439 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002440 member_vnf_index=member_vnf_index,
2441 vdu_index=vdu_index,
2442 vdu_name=vdu_name,
tierno626e0152019-11-29 14:16:16 +00002443 deploy_params=deploy_params_vdu,
quilesj7e13aeb2019-10-08 13:34:55 +02002444 descriptor_config=descriptor_config,
2445 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002446 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002447 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002448 )
bravof922c4172020-11-24 21:21:43 -03002449 for kdud in get_kdu_list(vnfd):
calvinosanch9f9c6f22019-11-04 13:37:39 +01002450 kdu_name = kdud["name"]
bravofe5a31bc2021-02-17 19:09:12 -03002451 descriptor_config = get_configuration(vnfd, kdu_name)
tierno588547c2020-07-01 15:30:20 +00002452 if descriptor_config:
calvinosanch9f9c6f22019-11-04 13:37:39 +01002453 vdu_id = None
2454 vdu_index = 0
2455 vdu_name = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002456 kdur = next(
2457 x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name
2458 )
bravof922c4172020-11-24 21:21:43 -03002459 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
tierno72ef84f2020-10-06 08:22:07 +00002460 if kdur.get("additionalParams"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002461 deploy_params_kdu = parse_yaml_strings(
2462 kdur["additionalParams"]
2463 )
tierno59d22d22018-09-25 18:10:19 +02002464
calvinosanch9f9c6f22019-11-04 13:37:39 +01002465 self._deploy_n2vc(
2466 logging_text=logging_text,
2467 db_nsr=db_nsr,
2468 db_vnfr=db_vnfr,
2469 nslcmop_id=nslcmop_id,
2470 nsr_id=nsr_id,
2471 nsi_id=nsi_id,
2472 vnfd_id=vnfd_id,
2473 vdu_id=vdu_id,
2474 kdu_name=kdu_name,
2475 member_vnf_index=member_vnf_index,
2476 vdu_index=vdu_index,
2477 vdu_name=vdu_name,
tierno72ef84f2020-10-06 08:22:07 +00002478 deploy_params=deploy_params_kdu,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002479 descriptor_config=descriptor_config,
2480 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002481 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002482 stage=stage,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002483 )
tierno59d22d22018-09-25 18:10:19 +02002484
tierno1b633412019-02-25 16:48:23 +00002485 # Check if this NS has a charm configuration
tiernod8323042019-08-09 11:32:23 +00002486 descriptor_config = nsd.get("ns-configuration")
2487 if descriptor_config and descriptor_config.get("juju"):
2488 vnfd_id = None
2489 db_vnfr = None
2490 member_vnf_index = None
2491 vdu_id = None
calvinosanch9f9c6f22019-11-04 13:37:39 +01002492 kdu_name = None
tiernod8323042019-08-09 11:32:23 +00002493 vdu_index = 0
2494 vdu_name = None
tierno1b633412019-02-25 16:48:23 +00002495
tiernod8323042019-08-09 11:32:23 +00002496 # Get additional parameters
David Garcia40603572020-12-10 20:10:53 +01002497 deploy_params = {"OSM": {"vim_account_id": ns_params["vimAccountId"]}}
tiernod8323042019-08-09 11:32:23 +00002498 if db_nsr.get("additionalParamsForNs"):
garciadeblas5697b8b2021-03-24 09:17:02 +01002499 deploy_params.update(
2500 parse_yaml_strings(db_nsr["additionalParamsForNs"].copy())
2501 )
tiernod8323042019-08-09 11:32:23 +00002502 base_folder = nsd["_admin"]["storage"]
quilesj7e13aeb2019-10-08 13:34:55 +02002503 self._deploy_n2vc(
2504 logging_text=logging_text,
2505 db_nsr=db_nsr,
2506 db_vnfr=db_vnfr,
2507 nslcmop_id=nslcmop_id,
2508 nsr_id=nsr_id,
2509 nsi_id=nsi_id,
2510 vnfd_id=vnfd_id,
2511 vdu_id=vdu_id,
calvinosanch9f9c6f22019-11-04 13:37:39 +01002512 kdu_name=kdu_name,
quilesj7e13aeb2019-10-08 13:34:55 +02002513 member_vnf_index=member_vnf_index,
2514 vdu_index=vdu_index,
2515 vdu_name=vdu_name,
2516 deploy_params=deploy_params,
2517 descriptor_config=descriptor_config,
2518 base_folder=base_folder,
tierno8e2fae72020-04-01 15:21:15 +00002519 task_instantiation_info=tasks_dict_info,
garciadeblas5697b8b2021-03-24 09:17:02 +01002520 stage=stage,
quilesj7e13aeb2019-10-08 13:34:55 +02002521 )
tierno1b633412019-02-25 16:48:23 +00002522
tiernoe876f672020-02-13 14:34:48 +00002523 # rest of staff will be done at finally
tierno1b633412019-02-25 16:48:23 +00002524
garciadeblas5697b8b2021-03-24 09:17:02 +01002525 except (
2526 ROclient.ROClientException,
2527 DbException,
2528 LcmException,
2529 N2VCException,
2530 ) as e:
2531 self.logger.error(
2532 logging_text + "Exit Exception while '{}': {}".format(stage[1], e)
2533 )
tierno59d22d22018-09-25 18:10:19 +02002534 exc = e
2535 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01002536 self.logger.error(
2537 logging_text + "Cancelled Exception while '{}'".format(stage[1])
2538 )
tierno59d22d22018-09-25 18:10:19 +02002539 exc = "Operation was cancelled"
2540 except Exception as e:
2541 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01002542 self.logger.critical(
2543 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
2544 exc_info=True,
2545 )
tierno59d22d22018-09-25 18:10:19 +02002546 finally:
2547 if exc:
tiernoe876f672020-02-13 14:34:48 +00002548 error_list.append(str(exc))
tiernobaa51102018-12-14 13:16:18 +00002549 try:
tiernoe876f672020-02-13 14:34:48 +00002550 # wait for pending tasks
2551 if tasks_dict_info:
2552 stage[1] = "Waiting for instantiate pending tasks."
2553 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01002554 error_list += await self._wait_for_tasks(
2555 logging_text,
2556 tasks_dict_info,
2557 timeout_ns_deploy,
2558 stage,
2559 nslcmop_id,
2560 nsr_id=nsr_id,
2561 )
tiernoe876f672020-02-13 14:34:48 +00002562 stage[1] = stage[2] = ""
2563 except asyncio.CancelledError:
2564 error_list.append("Cancelled")
2565 # TODO cancel all tasks
2566 except Exception as exc:
2567 error_list.append(str(exc))
quilesj4cda56b2019-12-05 10:02:20 +00002568
tiernoe876f672020-02-13 14:34:48 +00002569 # update operation-status
2570 db_nsr_update["operational-status"] = "running"
2571 # let's begin with VCA 'configured' status (later we can change it)
2572 db_nsr_update["config-status"] = "configured"
2573 for task, task_name in tasks_dict_info.items():
2574 if not task.done() or task.cancelled() or task.exception():
2575 if task_name.startswith(self.task_name_deploy_vca):
2576 # A N2VC task is pending
2577 db_nsr_update["config-status"] = "failed"
quilesj4cda56b2019-12-05 10:02:20 +00002578 else:
tiernoe876f672020-02-13 14:34:48 +00002579 # RO or KDU task is pending
2580 db_nsr_update["operational-status"] = "failed"
quilesj3655ae02019-12-12 16:08:35 +00002581
tiernoe876f672020-02-13 14:34:48 +00002582 # update status at database
2583 if error_list:
tiernoa2143262020-03-27 16:20:40 +00002584 error_detail = ". ".join(error_list)
tiernoe876f672020-02-13 14:34:48 +00002585 self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01002586 error_description_nslcmop = "{} Detail: {}".format(
2587 stage[0], error_detail
2588 )
2589 error_description_nsr = "Operation: INSTANTIATING.{}, {}".format(
2590 nslcmop_id, stage[0]
2591 )
quilesj3655ae02019-12-12 16:08:35 +00002592
garciadeblas5697b8b2021-03-24 09:17:02 +01002593 db_nsr_update["detailed-status"] = (
2594 error_description_nsr + " Detail: " + error_detail
2595 )
tiernoe876f672020-02-13 14:34:48 +00002596 db_nslcmop_update["detailed-status"] = error_detail
2597 nslcmop_operation_state = "FAILED"
2598 ns_state = "BROKEN"
2599 else:
tiernoa2143262020-03-27 16:20:40 +00002600 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00002601 error_description_nsr = error_description_nslcmop = None
2602 ns_state = "READY"
2603 db_nsr_update["detailed-status"] = "Done"
2604 db_nslcmop_update["detailed-status"] = "Done"
2605 nslcmop_operation_state = "COMPLETED"
quilesj4cda56b2019-12-05 10:02:20 +00002606
tiernoe876f672020-02-13 14:34:48 +00002607 if db_nsr:
2608 self._write_ns_status(
2609 nsr_id=nsr_id,
2610 ns_state=ns_state,
2611 current_operation="IDLE",
2612 current_operation_id=None,
2613 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00002614 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01002615 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00002616 )
tiernoa17d4f42020-04-28 09:59:23 +00002617 self._write_op_status(
2618 op_id=nslcmop_id,
2619 stage="",
2620 error_message=error_description_nslcmop,
2621 operation_state=nslcmop_operation_state,
2622 other_update=db_nslcmop_update,
2623 )
quilesj3655ae02019-12-12 16:08:35 +00002624
tierno59d22d22018-09-25 18:10:19 +02002625 if nslcmop_operation_state:
2626 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002627 await self.msg.aiowrite(
2628 "ns",
2629 "instantiated",
2630 {
2631 "nsr_id": nsr_id,
2632 "nslcmop_id": nslcmop_id,
2633 "operationState": nslcmop_operation_state,
2634 },
2635 loop=self.loop,
2636 )
tierno59d22d22018-09-25 18:10:19 +02002637 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002638 self.logger.error(
2639 logging_text + "kafka_write notification Exception {}".format(e)
2640 )
tierno59d22d22018-09-25 18:10:19 +02002641
2642 self.logger.debug(logging_text + "Exit")
2643 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_instantiate")
2644
David Garciac1fe90a2021-03-31 19:12:02 +02002645 async def _add_vca_relations(
2646 self,
2647 logging_text,
2648 nsr_id,
2649 vca_index: int,
2650 timeout: int = 3600,
2651 vca_type: str = None,
2652 vca_id: str = None,
2653 ) -> bool:
quilesj63f90042020-01-17 09:53:55 +00002654
2655 # steps:
2656 # 1. find all relations for this VCA
2657 # 2. wait for other peers related
2658 # 3. add relations
2659
2660 try:
tierno588547c2020-07-01 15:30:20 +00002661 vca_type = vca_type or "lxc_proxy_charm"
quilesj63f90042020-01-17 09:53:55 +00002662
2663 # STEP 1: find all relations for this VCA
2664
2665 # read nsr record
2666 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garcia171f3542020-05-21 16:41:07 +02002667 nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
quilesj63f90042020-01-17 09:53:55 +00002668
2669 # this VCA data
garciadeblas5697b8b2021-03-24 09:17:02 +01002670 my_vca = deep_get(db_nsr, ("_admin", "deployed", "VCA"))[vca_index]
quilesj63f90042020-01-17 09:53:55 +00002671
2672 # read all ns-configuration relations
2673 ns_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002674 db_ns_relations = deep_get(nsd, ("ns-configuration", "relation"))
quilesj63f90042020-01-17 09:53:55 +00002675 if db_ns_relations:
2676 for r in db_ns_relations:
2677 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002678 if my_vca.get("member-vnf-index") in (
2679 r.get("entities")[0].get("id"),
2680 r.get("entities")[1].get("id"),
2681 ):
quilesj63f90042020-01-17 09:53:55 +00002682 ns_relations.append(r)
2683
2684 # read all vnf-configuration relations
2685 vnf_relations = list()
garciadeblas5697b8b2021-03-24 09:17:02 +01002686 db_vnfd_list = db_nsr.get("vnfd-id")
quilesj63f90042020-01-17 09:53:55 +00002687 if db_vnfd_list:
2688 for vnfd in db_vnfd_list:
aktas45966a02021-05-04 19:32:45 +03002689 db_vnf_relations = None
quilesj63f90042020-01-17 09:53:55 +00002690 db_vnfd = self.db.get_one("vnfds", {"_id": vnfd})
aktas45966a02021-05-04 19:32:45 +03002691 db_vnf_configuration = get_configuration(db_vnfd, db_vnfd["id"])
2692 if db_vnf_configuration:
2693 db_vnf_relations = db_vnf_configuration.get("relation", [])
quilesj63f90042020-01-17 09:53:55 +00002694 if db_vnf_relations:
2695 for r in db_vnf_relations:
2696 # check if this VCA is in the relation
garciadeblas5697b8b2021-03-24 09:17:02 +01002697 if my_vca.get("vdu_id") in (
2698 r.get("entities")[0].get("id"),
2699 r.get("entities")[1].get("id"),
2700 ):
quilesj63f90042020-01-17 09:53:55 +00002701 vnf_relations.append(r)
2702
2703 # if no relations, terminate
2704 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002705 self.logger.debug(logging_text + " No relations")
quilesj63f90042020-01-17 09:53:55 +00002706 return True
2707
garciadeblas5697b8b2021-03-24 09:17:02 +01002708 self.logger.debug(
2709 logging_text
2710 + " adding relations\n {}\n {}".format(
2711 ns_relations, vnf_relations
2712 )
2713 )
quilesj63f90042020-01-17 09:53:55 +00002714
2715 # add all relations
2716 start = time()
2717 while True:
2718 # check timeout
2719 now = time()
2720 if now - start >= timeout:
garciadeblas5697b8b2021-03-24 09:17:02 +01002721 self.logger.error(logging_text + " : timeout adding relations")
quilesj63f90042020-01-17 09:53:55 +00002722 return False
2723
2724 # reload nsr from database (we need to update record: _admin.deloyed.VCA)
2725 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
2726
2727 # for each defined NS relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002728 for r in ns_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002729 from_vca_ee_id = None
2730 to_vca_ee_id = None
2731 from_vca_endpoint = None
2732 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002733 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002734 for vca in vca_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01002735 if vca.get("member-vnf-index") == r.get("entities")[0].get(
2736 "id"
2737 ) and vca.get("config_sw_installed"):
2738 from_vca_ee_id = vca.get("ee_id")
2739 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2740 if vca.get("member-vnf-index") == r.get("entities")[1].get(
2741 "id"
2742 ) and vca.get("config_sw_installed"):
2743 to_vca_ee_id = vca.get("ee_id")
2744 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002745 if from_vca_ee_id and to_vca_ee_id:
2746 # add relation
tierno588547c2020-07-01 15:30:20 +00002747 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002748 ee_id_1=from_vca_ee_id,
2749 ee_id_2=to_vca_ee_id,
2750 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002751 endpoint_2=to_vca_endpoint,
2752 vca_id=vca_id,
2753 )
quilesj63f90042020-01-17 09:53:55 +00002754 # remove entry from relations list
2755 ns_relations.remove(r)
2756 else:
2757 # check failed peers
2758 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002759 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002760 if vca_status_list:
2761 for i in range(len(vca_list)):
2762 vca = vca_list[i]
2763 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002764 if vca.get("member-vnf-index") == r.get("entities")[
2765 0
2766 ].get("id"):
2767 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002768 # peer broken: remove relation from list
2769 ns_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002770 if vca.get("member-vnf-index") == r.get("entities")[
2771 1
2772 ].get("id"):
2773 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002774 # peer broken: remove relation from list
2775 ns_relations.remove(r)
2776 except Exception:
2777 # ignore
2778 pass
2779
2780 # for each defined VNF relation, find the VCA's related
tierno364c4572020-09-14 12:11:32 +00002781 for r in vnf_relations.copy():
quilesj63f90042020-01-17 09:53:55 +00002782 from_vca_ee_id = None
2783 to_vca_ee_id = None
2784 from_vca_endpoint = None
2785 to_vca_endpoint = None
garciadeblas5697b8b2021-03-24 09:17:02 +01002786 vca_list = deep_get(db_nsr, ("_admin", "deployed", "VCA"))
quilesj63f90042020-01-17 09:53:55 +00002787 for vca in vca_list:
David Garcia97be6832020-09-09 15:40:44 +02002788 key_to_check = "vdu_id"
2789 if vca.get("vdu_id") is None:
2790 key_to_check = "vnfd_id"
garciadeblas5697b8b2021-03-24 09:17:02 +01002791 if vca.get(key_to_check) == r.get("entities")[0].get(
2792 "id"
2793 ) and vca.get("config_sw_installed"):
2794 from_vca_ee_id = vca.get("ee_id")
2795 from_vca_endpoint = r.get("entities")[0].get("endpoint")
2796 if vca.get(key_to_check) == r.get("entities")[1].get(
2797 "id"
2798 ) and vca.get("config_sw_installed"):
2799 to_vca_ee_id = vca.get("ee_id")
2800 to_vca_endpoint = r.get("entities")[1].get("endpoint")
quilesj63f90042020-01-17 09:53:55 +00002801 if from_vca_ee_id and to_vca_ee_id:
2802 # add relation
tierno588547c2020-07-01 15:30:20 +00002803 await self.vca_map[vca_type].add_relation(
quilesj63f90042020-01-17 09:53:55 +00002804 ee_id_1=from_vca_ee_id,
2805 ee_id_2=to_vca_ee_id,
2806 endpoint_1=from_vca_endpoint,
David Garciac1fe90a2021-03-31 19:12:02 +02002807 endpoint_2=to_vca_endpoint,
2808 vca_id=vca_id,
2809 )
quilesj63f90042020-01-17 09:53:55 +00002810 # remove entry from relations list
2811 vnf_relations.remove(r)
2812 else:
2813 # check failed peers
2814 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002815 vca_status_list = db_nsr.get("configurationStatus")
quilesj63f90042020-01-17 09:53:55 +00002816 if vca_status_list:
2817 for i in range(len(vca_list)):
2818 vca = vca_list[i]
2819 vca_status = vca_status_list[i]
garciadeblas5697b8b2021-03-24 09:17:02 +01002820 if vca.get("vdu_id") == r.get("entities")[0].get(
2821 "id"
2822 ):
2823 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002824 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002825 vnf_relations.remove(r)
garciadeblas5697b8b2021-03-24 09:17:02 +01002826 if vca.get("vdu_id") == r.get("entities")[1].get(
2827 "id"
2828 ):
2829 if vca_status.get("status") == "BROKEN":
quilesj63f90042020-01-17 09:53:55 +00002830 # peer broken: remove relation from list
David Garcia092afbd2020-08-25 13:17:25 +02002831 vnf_relations.remove(r)
quilesj63f90042020-01-17 09:53:55 +00002832 except Exception:
2833 # ignore
2834 pass
2835
2836 # wait for next try
2837 await asyncio.sleep(5.0)
2838
2839 if not ns_relations and not vnf_relations:
garciadeblas5697b8b2021-03-24 09:17:02 +01002840 self.logger.debug("Relations added")
quilesj63f90042020-01-17 09:53:55 +00002841 break
2842
2843 return True
2844
2845 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01002846 self.logger.warn(logging_text + " ERROR adding relations: {}".format(e))
quilesj63f90042020-01-17 09:53:55 +00002847 return False
2848
garciadeblas5697b8b2021-03-24 09:17:02 +01002849 async def _install_kdu(
2850 self,
2851 nsr_id: str,
2852 nsr_db_path: str,
2853 vnfr_data: dict,
2854 kdu_index: int,
2855 kdud: dict,
2856 vnfd: dict,
2857 k8s_instance_info: dict,
2858 k8params: dict = None,
2859 timeout: int = 600,
2860 vca_id: str = None,
2861 ):
lloretgalleg7c121132020-07-08 07:53:22 +00002862
tiernob9018152020-04-16 14:18:24 +00002863 try:
lloretgalleg7c121132020-07-08 07:53:22 +00002864 k8sclustertype = k8s_instance_info["k8scluster-type"]
2865 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01002866 db_dict_install = {
2867 "collection": "nsrs",
2868 "filter": {"_id": nsr_id},
2869 "path": nsr_db_path,
2870 }
lloretgalleg7c121132020-07-08 07:53:22 +00002871
romeromonser4e71ab62021-05-28 12:06:34 +02002872 if k8s_instance_info.get("kdu-deployment-name"):
2873 kdu_instance = k8s_instance_info.get("kdu-deployment-name")
2874 else:
2875 kdu_instance = self.k8scluster_map[
2876 k8sclustertype
2877 ].generate_kdu_instance_name(
2878 db_dict=db_dict_install,
2879 kdu_model=k8s_instance_info["kdu-model"],
2880 kdu_name=k8s_instance_info["kdu-name"],
2881 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002882 self.update_db_2(
2883 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2884 )
David Garciad64e2742021-02-25 20:19:18 +01002885 await self.k8scluster_map[k8sclustertype].install(
lloretgalleg7c121132020-07-08 07:53:22 +00002886 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2887 kdu_model=k8s_instance_info["kdu-model"],
2888 atomic=True,
2889 params=k8params,
2890 db_dict=db_dict_install,
2891 timeout=timeout,
2892 kdu_name=k8s_instance_info["kdu-name"],
David Garciad64e2742021-02-25 20:19:18 +01002893 namespace=k8s_instance_info["namespace"],
2894 kdu_instance=kdu_instance,
David Garciac1fe90a2021-03-31 19:12:02 +02002895 vca_id=vca_id,
David Garciad64e2742021-02-25 20:19:18 +01002896 )
garciadeblas5697b8b2021-03-24 09:17:02 +01002897 self.update_db_2(
2898 "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance}
2899 )
lloretgalleg7c121132020-07-08 07:53:22 +00002900
2901 # Obtain services to obtain management service ip
2902 services = await self.k8scluster_map[k8sclustertype].get_services(
2903 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2904 kdu_instance=kdu_instance,
garciadeblas5697b8b2021-03-24 09:17:02 +01002905 namespace=k8s_instance_info["namespace"],
2906 )
lloretgalleg7c121132020-07-08 07:53:22 +00002907
2908 # Obtain management service info (if exists)
tierno7ecbc342020-09-21 14:05:39 +00002909 vnfr_update_dict = {}
bravof6ec62b72021-02-25 17:20:35 -03002910 kdu_config = get_configuration(vnfd, kdud["name"])
2911 if kdu_config:
2912 target_ee_list = kdu_config.get("execution-environment-list", [])
2913 else:
2914 target_ee_list = []
2915
lloretgalleg7c121132020-07-08 07:53:22 +00002916 if services:
tierno7ecbc342020-09-21 14:05:39 +00002917 vnfr_update_dict["kdur.{}.services".format(kdu_index)] = services
garciadeblas5697b8b2021-03-24 09:17:02 +01002918 mgmt_services = [
2919 service
2920 for service in kdud.get("service", [])
2921 if service.get("mgmt-service")
2922 ]
lloretgalleg7c121132020-07-08 07:53:22 +00002923 for mgmt_service in mgmt_services:
2924 for service in services:
2925 if service["name"].startswith(mgmt_service["name"]):
2926 # Mgmt service found, Obtain service ip
2927 ip = service.get("external_ip", service.get("cluster_ip"))
2928 if isinstance(ip, list) and len(ip) == 1:
2929 ip = ip[0]
2930
garciadeblas5697b8b2021-03-24 09:17:02 +01002931 vnfr_update_dict[
2932 "kdur.{}.ip-address".format(kdu_index)
2933 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00002934
2935 # Check if must update also mgmt ip at the vnf
garciadeblas5697b8b2021-03-24 09:17:02 +01002936 service_external_cp = mgmt_service.get(
2937 "external-connection-point-ref"
2938 )
lloretgalleg7c121132020-07-08 07:53:22 +00002939 if service_external_cp:
garciadeblas5697b8b2021-03-24 09:17:02 +01002940 if (
2941 deep_get(vnfd, ("mgmt-interface", "cp"))
2942 == service_external_cp
2943 ):
lloretgalleg7c121132020-07-08 07:53:22 +00002944 vnfr_update_dict["ip-address"] = ip
2945
bravof6ec62b72021-02-25 17:20:35 -03002946 if find_in_list(
2947 target_ee_list,
garciadeblas5697b8b2021-03-24 09:17:02 +01002948 lambda ee: ee.get(
2949 "external-connection-point-ref", ""
2950 )
2951 == service_external_cp,
bravof6ec62b72021-02-25 17:20:35 -03002952 ):
garciadeblas5697b8b2021-03-24 09:17:02 +01002953 vnfr_update_dict[
2954 "kdur.{}.ip-address".format(kdu_index)
2955 ] = ip
lloretgalleg7c121132020-07-08 07:53:22 +00002956 break
2957 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01002958 self.logger.warn(
2959 "Mgmt service name: {} not found".format(
2960 mgmt_service["name"]
2961 )
2962 )
lloretgalleg7c121132020-07-08 07:53:22 +00002963
tierno7ecbc342020-09-21 14:05:39 +00002964 vnfr_update_dict["kdur.{}.status".format(kdu_index)] = "READY"
2965 self.update_db_2("vnfrs", vnfr_data.get("_id"), vnfr_update_dict)
lloretgalleg7c121132020-07-08 07:53:22 +00002966
bravof9a256db2021-02-22 18:02:07 -03002967 kdu_config = get_configuration(vnfd, k8s_instance_info["kdu-name"])
garciadeblas5697b8b2021-03-24 09:17:02 +01002968 if (
2969 kdu_config
2970 and kdu_config.get("initial-config-primitive")
2971 and get_juju_ee_ref(vnfd, k8s_instance_info["kdu-name"]) is None
2972 ):
2973 initial_config_primitive_list = kdu_config.get(
2974 "initial-config-primitive"
2975 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02002976 initial_config_primitive_list.sort(key=lambda val: int(val["seq"]))
2977
2978 for initial_config_primitive in initial_config_primitive_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01002979 primitive_params_ = self._map_primitive_params(
2980 initial_config_primitive, {}, {}
2981 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02002982
2983 await asyncio.wait_for(
2984 self.k8scluster_map[k8sclustertype].exec_primitive(
2985 cluster_uuid=k8s_instance_info["k8scluster-uuid"],
2986 kdu_instance=kdu_instance,
2987 primitive_name=initial_config_primitive["name"],
garciadeblas5697b8b2021-03-24 09:17:02 +01002988 params=primitive_params_,
2989 db_dict=db_dict_install,
David Garciac1fe90a2021-03-31 19:12:02 +02002990 vca_id=vca_id,
2991 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01002992 timeout=timeout,
David Garciac1fe90a2021-03-31 19:12:02 +02002993 )
Dominik Fleischmannc1975dd2020-08-19 12:17:51 +02002994
tiernob9018152020-04-16 14:18:24 +00002995 except Exception as e:
lloretgalleg7c121132020-07-08 07:53:22 +00002996 # Prepare update db with error and raise exception
tiernob9018152020-04-16 14:18:24 +00002997 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01002998 self.update_db_2(
2999 "nsrs", nsr_id, {nsr_db_path + ".detailed-status": str(e)}
3000 )
3001 self.update_db_2(
3002 "vnfrs",
3003 vnfr_data.get("_id"),
3004 {"kdur.{}.status".format(kdu_index): "ERROR"},
3005 )
tiernob9018152020-04-16 14:18:24 +00003006 except Exception:
lloretgalleg7c121132020-07-08 07:53:22 +00003007 # ignore to keep original exception
tiernob9018152020-04-16 14:18:24 +00003008 pass
lloretgalleg7c121132020-07-08 07:53:22 +00003009 # reraise original error
3010 raise
3011
3012 return kdu_instance
tiernob9018152020-04-16 14:18:24 +00003013
garciadeblas5697b8b2021-03-24 09:17:02 +01003014 async def deploy_kdus(
3015 self,
3016 logging_text,
3017 nsr_id,
3018 nslcmop_id,
3019 db_vnfrs,
3020 db_vnfds,
3021 task_instantiation_info,
3022 ):
calvinosanch9f9c6f22019-11-04 13:37:39 +01003023 # Launch kdus if present in the descriptor
tierno626e0152019-11-29 14:16:16 +00003024
garciadeblas5697b8b2021-03-24 09:17:02 +01003025 k8scluster_id_2_uuic = {
3026 "helm-chart-v3": {},
3027 "helm-chart": {},
3028 "juju-bundle": {},
3029 }
tierno626e0152019-11-29 14:16:16 +00003030
tierno16f4a4e2020-07-20 09:05:51 +00003031 async def _get_cluster_id(cluster_id, cluster_type):
tierno626e0152019-11-29 14:16:16 +00003032 nonlocal k8scluster_id_2_uuic
3033 if cluster_id in k8scluster_id_2_uuic[cluster_type]:
3034 return k8scluster_id_2_uuic[cluster_type][cluster_id]
3035
tierno16f4a4e2020-07-20 09:05:51 +00003036 # check if K8scluster is creating and wait look if previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01003037 task_name, task_dependency = self.lcm_tasks.lookfor_related(
3038 "k8scluster", cluster_id
3039 )
tierno16f4a4e2020-07-20 09:05:51 +00003040 if task_dependency:
garciadeblas5697b8b2021-03-24 09:17:02 +01003041 text = "Waiting for related tasks '{}' on k8scluster {} to be completed".format(
3042 task_name, cluster_id
3043 )
tierno16f4a4e2020-07-20 09:05:51 +00003044 self.logger.debug(logging_text + text)
3045 await asyncio.wait(task_dependency, timeout=3600)
3046
garciadeblas5697b8b2021-03-24 09:17:02 +01003047 db_k8scluster = self.db.get_one(
3048 "k8sclusters", {"_id": cluster_id}, fail_on_empty=False
3049 )
tierno626e0152019-11-29 14:16:16 +00003050 if not db_k8scluster:
3051 raise LcmException("K8s cluster {} cannot be found".format(cluster_id))
tierno16f4a4e2020-07-20 09:05:51 +00003052
tierno626e0152019-11-29 14:16:16 +00003053 k8s_id = deep_get(db_k8scluster, ("_admin", cluster_type, "id"))
3054 if not k8s_id:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003055 if cluster_type == "helm-chart-v3":
3056 try:
3057 # backward compatibility for existing clusters that have not been initialized for helm v3
garciadeblas5697b8b2021-03-24 09:17:02 +01003058 k8s_credentials = yaml.safe_dump(
3059 db_k8scluster.get("credentials")
3060 )
3061 k8s_id, uninstall_sw = await self.k8sclusterhelm3.init_env(
3062 k8s_credentials, reuse_cluster_uuid=cluster_id
3063 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003064 db_k8scluster_update = {}
3065 db_k8scluster_update["_admin.helm-chart-v3.error_msg"] = None
3066 db_k8scluster_update["_admin.helm-chart-v3.id"] = k8s_id
garciadeblas5697b8b2021-03-24 09:17:02 +01003067 db_k8scluster_update[
3068 "_admin.helm-chart-v3.created"
3069 ] = uninstall_sw
3070 db_k8scluster_update[
3071 "_admin.helm-chart-v3.operationalState"
3072 ] = "ENABLED"
3073 self.update_db_2(
3074 "k8sclusters", cluster_id, db_k8scluster_update
3075 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003076 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003077 self.logger.error(
3078 logging_text
3079 + "error initializing helm-v3 cluster: {}".format(str(e))
3080 )
3081 raise LcmException(
3082 "K8s cluster '{}' has not been initialized for '{}'".format(
3083 cluster_id, cluster_type
3084 )
3085 )
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003086 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003087 raise LcmException(
3088 "K8s cluster '{}' has not been initialized for '{}'".format(
3089 cluster_id, cluster_type
3090 )
3091 )
tierno626e0152019-11-29 14:16:16 +00003092 k8scluster_id_2_uuic[cluster_type][cluster_id] = k8s_id
3093 return k8s_id
3094
3095 logging_text += "Deploy kdus: "
tiernoe876f672020-02-13 14:34:48 +00003096 step = ""
calvinosanch9f9c6f22019-11-04 13:37:39 +01003097 try:
tierno626e0152019-11-29 14:16:16 +00003098 db_nsr_update = {"_admin.deployed.K8s": []}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003099 self.update_db_2("nsrs", nsr_id, db_nsr_update)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003100
tierno626e0152019-11-29 14:16:16 +00003101 index = 0
tiernoe876f672020-02-13 14:34:48 +00003102 updated_cluster_list = []
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003103 updated_v3_cluster_list = []
tiernoe876f672020-02-13 14:34:48 +00003104
tierno626e0152019-11-29 14:16:16 +00003105 for vnfr_data in db_vnfrs.values():
David Garciac1fe90a2021-03-31 19:12:02 +02003106 vca_id = self.get_vca_id(vnfr_data, {})
lloretgalleg7c121132020-07-08 07:53:22 +00003107 for kdu_index, kdur in enumerate(get_iterable(vnfr_data, "kdur")):
3108 # Step 0: Prepare and set parameters
bravof922c4172020-11-24 21:21:43 -03003109 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
garciadeblas5697b8b2021-03-24 09:17:02 +01003110 vnfd_id = vnfr_data.get("vnfd-id")
3111 vnfd_with_id = find_in_list(
3112 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3113 )
3114 kdud = next(
3115 kdud
3116 for kdud in vnfd_with_id["kdu"]
3117 if kdud["name"] == kdur["kdu-name"]
3118 )
tiernode1584f2020-04-07 09:07:33 +00003119 namespace = kdur.get("k8s-namespace")
romeromonser4e71ab62021-05-28 12:06:34 +02003120 kdu_deployment_name = kdur.get("kdu-deployment-name")
tierno626e0152019-11-29 14:16:16 +00003121 if kdur.get("helm-chart"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003122 kdumodel = kdur["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003123 # Default version: helm3, if helm-version is v2 assign v2
3124 k8sclustertype = "helm-chart-v3"
3125 self.logger.debug("kdur: {}".format(kdur))
garciadeblas5697b8b2021-03-24 09:17:02 +01003126 if (
3127 kdur.get("helm-version")
3128 and kdur.get("helm-version") == "v2"
3129 ):
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003130 k8sclustertype = "helm-chart"
tierno626e0152019-11-29 14:16:16 +00003131 elif kdur.get("juju-bundle"):
lloretgalleg07e53f52020-12-15 10:54:02 +00003132 kdumodel = kdur["juju-bundle"]
tiernoe876f672020-02-13 14:34:48 +00003133 k8sclustertype = "juju-bundle"
tierno626e0152019-11-29 14:16:16 +00003134 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003135 raise LcmException(
3136 "kdu type for kdu='{}.{}' is neither helm-chart nor "
3137 "juju-bundle. Maybe an old NBI version is running".format(
3138 vnfr_data["member-vnf-index-ref"], kdur["kdu-name"]
3139 )
3140 )
quilesjacde94f2020-01-23 10:07:08 +00003141 # check if kdumodel is a file and exists
3142 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01003143 vnfd_with_id = find_in_list(
3144 db_vnfds, lambda vnfd: vnfd["_id"] == vnfd_id
3145 )
3146 storage = deep_get(vnfd_with_id, ("_admin", "storage"))
3147 if storage and storage.get(
3148 "pkg-dir"
3149 ): # may be not present if vnfd has not artifacts
tierno51183952020-04-03 15:48:18 +00003150 # path format: /vnfdid/pkkdir/helm-charts|juju-bundles/kdumodel
garciadeblas5697b8b2021-03-24 09:17:02 +01003151 filename = "{}/{}/{}s/{}".format(
3152 storage["folder"],
3153 storage["pkg-dir"],
3154 k8sclustertype,
3155 kdumodel,
3156 )
3157 if self.fs.file_exists(
3158 filename, mode="file"
3159 ) or self.fs.file_exists(filename, mode="dir"):
tierno51183952020-04-03 15:48:18 +00003160 kdumodel = self.fs.path + filename
3161 except (asyncio.TimeoutError, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00003162 raise
garciadeblas5697b8b2021-03-24 09:17:02 +01003163 except Exception: # it is not a file
quilesjacde94f2020-01-23 10:07:08 +00003164 pass
lloretgallegedc5f332020-02-20 11:50:50 +01003165
tiernoe876f672020-02-13 14:34:48 +00003166 k8s_cluster_id = kdur["k8s-cluster"]["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003167 step = "Synchronize repos for k8s cluster '{}'".format(
3168 k8s_cluster_id
3169 )
tierno16f4a4e2020-07-20 09:05:51 +00003170 cluster_uuid = await _get_cluster_id(k8s_cluster_id, k8sclustertype)
lloretgallegedc5f332020-02-20 11:50:50 +01003171
lloretgalleg7c121132020-07-08 07:53:22 +00003172 # Synchronize repos
garciadeblas5697b8b2021-03-24 09:17:02 +01003173 if (
3174 k8sclustertype == "helm-chart"
3175 and cluster_uuid not in updated_cluster_list
3176 ) or (
3177 k8sclustertype == "helm-chart-v3"
3178 and cluster_uuid not in updated_v3_cluster_list
3179 ):
tiernoe876f672020-02-13 14:34:48 +00003180 del_repo_list, added_repo_dict = await asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003181 self.k8scluster_map[k8sclustertype].synchronize_repos(
3182 cluster_uuid=cluster_uuid
3183 )
3184 )
tiernoe876f672020-02-13 14:34:48 +00003185 if del_repo_list or added_repo_dict:
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003186 if k8sclustertype == "helm-chart":
garciadeblas5697b8b2021-03-24 09:17:02 +01003187 unset = {
3188 "_admin.helm_charts_added." + item: None
3189 for item in del_repo_list
3190 }
3191 updated = {
3192 "_admin.helm_charts_added." + item: name
3193 for item, name in added_repo_dict.items()
3194 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003195 updated_cluster_list.append(cluster_uuid)
3196 elif k8sclustertype == "helm-chart-v3":
garciadeblas5697b8b2021-03-24 09:17:02 +01003197 unset = {
3198 "_admin.helm_charts_v3_added." + item: None
3199 for item in del_repo_list
3200 }
3201 updated = {
3202 "_admin.helm_charts_v3_added." + item: name
3203 for item, name in added_repo_dict.items()
3204 }
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003205 updated_v3_cluster_list.append(cluster_uuid)
garciadeblas5697b8b2021-03-24 09:17:02 +01003206 self.logger.debug(
3207 logging_text + "repos synchronized on k8s cluster "
3208 "'{}' to_delete: {}, to_add: {}".format(
3209 k8s_cluster_id, del_repo_list, added_repo_dict
3210 )
3211 )
3212 self.db.set_one(
3213 "k8sclusters",
3214 {"_id": k8s_cluster_id},
3215 updated,
3216 unset=unset,
3217 )
lloretgallegedc5f332020-02-20 11:50:50 +01003218
lloretgalleg7c121132020-07-08 07:53:22 +00003219 # Instantiate kdu
garciadeblas5697b8b2021-03-24 09:17:02 +01003220 step = "Instantiating KDU {}.{} in k8s cluster {}".format(
3221 vnfr_data["member-vnf-index-ref"],
3222 kdur["kdu-name"],
3223 k8s_cluster_id,
3224 )
3225 k8s_instance_info = {
3226 "kdu-instance": None,
3227 "k8scluster-uuid": cluster_uuid,
3228 "k8scluster-type": k8sclustertype,
3229 "member-vnf-index": vnfr_data["member-vnf-index-ref"],
3230 "kdu-name": kdur["kdu-name"],
3231 "kdu-model": kdumodel,
3232 "namespace": namespace,
romeromonser4e71ab62021-05-28 12:06:34 +02003233 "kdu-deployment-name": kdu_deployment_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003234 }
tiernob9018152020-04-16 14:18:24 +00003235 db_path = "_admin.deployed.K8s.{}".format(index)
lloretgalleg7c121132020-07-08 07:53:22 +00003236 db_nsr_update[db_path] = k8s_instance_info
tierno626e0152019-11-29 14:16:16 +00003237 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003238 vnfd_with_id = find_in_list(
3239 db_vnfds, lambda vnf: vnf["_id"] == vnfd_id
3240 )
tiernoa2143262020-03-27 16:20:40 +00003241 task = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01003242 self._install_kdu(
3243 nsr_id,
3244 db_path,
3245 vnfr_data,
3246 kdu_index,
3247 kdud,
3248 vnfd_with_id,
3249 k8s_instance_info,
3250 k8params=desc_params,
3251 timeout=600,
3252 vca_id=vca_id,
3253 )
3254 )
3255 self.lcm_tasks.register(
3256 "ns",
3257 nsr_id,
3258 nslcmop_id,
3259 "instantiate_KDU-{}".format(index),
3260 task,
3261 )
3262 task_instantiation_info[task] = "Deploying KDU {}".format(
3263 kdur["kdu-name"]
3264 )
tiernoe876f672020-02-13 14:34:48 +00003265
tierno626e0152019-11-29 14:16:16 +00003266 index += 1
quilesjdd799ac2020-01-23 16:31:11 +00003267
tiernoe876f672020-02-13 14:34:48 +00003268 except (LcmException, asyncio.CancelledError):
3269 raise
calvinosanch9f9c6f22019-11-04 13:37:39 +01003270 except Exception as e:
tiernoe876f672020-02-13 14:34:48 +00003271 msg = "Exception {} while {}: {}".format(type(e).__name__, step, e)
3272 if isinstance(e, (N2VCException, DbException)):
3273 self.logger.error(logging_text + msg)
3274 else:
3275 self.logger.critical(logging_text + msg, exc_info=True)
quilesjdd799ac2020-01-23 16:31:11 +00003276 raise LcmException(msg)
calvinosanch9f9c6f22019-11-04 13:37:39 +01003277 finally:
calvinosanch9f9c6f22019-11-04 13:37:39 +01003278 if db_nsr_update:
3279 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoda6fb102019-11-23 00:36:52 +00003280
garciadeblas5697b8b2021-03-24 09:17:02 +01003281 def _deploy_n2vc(
3282 self,
3283 logging_text,
3284 db_nsr,
3285 db_vnfr,
3286 nslcmop_id,
3287 nsr_id,
3288 nsi_id,
3289 vnfd_id,
3290 vdu_id,
3291 kdu_name,
3292 member_vnf_index,
3293 vdu_index,
3294 vdu_name,
3295 deploy_params,
3296 descriptor_config,
3297 base_folder,
3298 task_instantiation_info,
3299 stage,
3300 ):
quilesj7e13aeb2019-10-08 13:34:55 +02003301 # launch instantiate_N2VC in a asyncio task and register task object
3302 # Look where information of this charm is at database <nsrs>._admin.deployed.VCA
3303 # if not found, create one entry and update database
quilesj7e13aeb2019-10-08 13:34:55 +02003304 # fill db_nsr._admin.deployed.VCA.<index>
tierno588547c2020-07-01 15:30:20 +00003305
garciadeblas5697b8b2021-03-24 09:17:02 +01003306 self.logger.debug(
3307 logging_text + "_deploy_n2vc vnfd_id={}, vdu_id={}".format(vnfd_id, vdu_id)
3308 )
bravof9a256db2021-02-22 18:02:07 -03003309 if "execution-environment-list" in descriptor_config:
3310 ee_list = descriptor_config.get("execution-environment-list", [])
David Garciab76442a2021-05-28 12:08:18 +02003311 elif "juju" in descriptor_config:
3312 ee_list = [descriptor_config] # ns charms
tierno588547c2020-07-01 15:30:20 +00003313 else: # other types as script are not supported
3314 ee_list = []
3315
3316 for ee_item in ee_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01003317 self.logger.debug(
3318 logging_text
3319 + "_deploy_n2vc ee_item juju={}, helm={}".format(
3320 ee_item.get("juju"), ee_item.get("helm-chart")
3321 )
3322 )
tiernoa278b842020-07-08 15:33:55 +00003323 ee_descriptor_id = ee_item.get("id")
tierno588547c2020-07-01 15:30:20 +00003324 if ee_item.get("juju"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003325 vca_name = ee_item["juju"].get("charm")
3326 vca_type = (
3327 "lxc_proxy_charm"
3328 if ee_item["juju"].get("charm") is not None
3329 else "native_charm"
3330 )
3331 if ee_item["juju"].get("cloud") == "k8s":
tierno588547c2020-07-01 15:30:20 +00003332 vca_type = "k8s_proxy_charm"
garciadeblas5697b8b2021-03-24 09:17:02 +01003333 elif ee_item["juju"].get("proxy") is False:
tierno588547c2020-07-01 15:30:20 +00003334 vca_type = "native_charm"
3335 elif ee_item.get("helm-chart"):
garciadeblas5697b8b2021-03-24 09:17:02 +01003336 vca_name = ee_item["helm-chart"]
lloretgalleg18ebc3a2020-10-22 09:54:51 +00003337 if ee_item.get("helm-version") and ee_item.get("helm-version") == "v2":
3338 vca_type = "helm"
3339 else:
3340 vca_type = "helm-v3"
tierno588547c2020-07-01 15:30:20 +00003341 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003342 self.logger.debug(
3343 logging_text + "skipping non juju neither charm configuration"
3344 )
quilesj7e13aeb2019-10-08 13:34:55 +02003345 continue
quilesj3655ae02019-12-12 16:08:35 +00003346
tierno588547c2020-07-01 15:30:20 +00003347 vca_index = -1
garciadeblas5697b8b2021-03-24 09:17:02 +01003348 for vca_index, vca_deployed in enumerate(
3349 db_nsr["_admin"]["deployed"]["VCA"]
3350 ):
tierno588547c2020-07-01 15:30:20 +00003351 if not vca_deployed:
3352 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003353 if (
3354 vca_deployed.get("member-vnf-index") == member_vnf_index
3355 and vca_deployed.get("vdu_id") == vdu_id
3356 and vca_deployed.get("kdu_name") == kdu_name
3357 and vca_deployed.get("vdu_count_index", 0) == vdu_index
3358 and vca_deployed.get("ee_descriptor_id") == ee_descriptor_id
3359 ):
tierno588547c2020-07-01 15:30:20 +00003360 break
3361 else:
3362 # not found, create one.
garciadeblas5697b8b2021-03-24 09:17:02 +01003363 target = (
3364 "ns" if not member_vnf_index else "vnf/{}".format(member_vnf_index)
3365 )
tiernoa278b842020-07-08 15:33:55 +00003366 if vdu_id:
3367 target += "/vdu/{}/{}".format(vdu_id, vdu_index or 0)
3368 elif kdu_name:
3369 target += "/kdu/{}".format(kdu_name)
tierno588547c2020-07-01 15:30:20 +00003370 vca_deployed = {
tiernoa278b842020-07-08 15:33:55 +00003371 "target_element": target,
3372 # ^ target_element will replace member-vnf-index, kdu_name, vdu_id ... in a single string
tierno588547c2020-07-01 15:30:20 +00003373 "member-vnf-index": member_vnf_index,
3374 "vdu_id": vdu_id,
3375 "kdu_name": kdu_name,
3376 "vdu_count_index": vdu_index,
3377 "operational-status": "init", # TODO revise
3378 "detailed-status": "", # TODO revise
garciadeblas5697b8b2021-03-24 09:17:02 +01003379 "step": "initial-deploy", # TODO revise
tierno588547c2020-07-01 15:30:20 +00003380 "vnfd_id": vnfd_id,
3381 "vdu_name": vdu_name,
tiernoa278b842020-07-08 15:33:55 +00003382 "type": vca_type,
garciadeblas5697b8b2021-03-24 09:17:02 +01003383 "ee_descriptor_id": ee_descriptor_id,
tierno588547c2020-07-01 15:30:20 +00003384 }
3385 vca_index += 1
quilesj3655ae02019-12-12 16:08:35 +00003386
tierno588547c2020-07-01 15:30:20 +00003387 # create VCA and configurationStatus in db
3388 db_dict = {
3389 "_admin.deployed.VCA.{}".format(vca_index): vca_deployed,
garciadeblas5697b8b2021-03-24 09:17:02 +01003390 "configurationStatus.{}".format(vca_index): dict(),
tierno588547c2020-07-01 15:30:20 +00003391 }
3392 self.update_db_2("nsrs", nsr_id, db_dict)
quilesj7e13aeb2019-10-08 13:34:55 +02003393
tierno588547c2020-07-01 15:30:20 +00003394 db_nsr["_admin"]["deployed"]["VCA"].append(vca_deployed)
3395
bravof922c4172020-11-24 21:21:43 -03003396 self.logger.debug("N2VC > NSR_ID > {}".format(nsr_id))
3397 self.logger.debug("N2VC > DB_NSR > {}".format(db_nsr))
3398 self.logger.debug("N2VC > VCA_DEPLOYED > {}".format(vca_deployed))
3399
tierno588547c2020-07-01 15:30:20 +00003400 # Launch task
3401 task_n2vc = asyncio.ensure_future(
3402 self.instantiate_N2VC(
3403 logging_text=logging_text,
3404 vca_index=vca_index,
3405 nsi_id=nsi_id,
3406 db_nsr=db_nsr,
3407 db_vnfr=db_vnfr,
3408 vdu_id=vdu_id,
3409 kdu_name=kdu_name,
3410 vdu_index=vdu_index,
3411 deploy_params=deploy_params,
3412 config_descriptor=descriptor_config,
3413 base_folder=base_folder,
3414 nslcmop_id=nslcmop_id,
3415 stage=stage,
3416 vca_type=vca_type,
tiernob996d942020-07-03 14:52:28 +00003417 vca_name=vca_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01003418 ee_config_descriptor=ee_item,
tierno588547c2020-07-01 15:30:20 +00003419 )
quilesj7e13aeb2019-10-08 13:34:55 +02003420 )
garciadeblas5697b8b2021-03-24 09:17:02 +01003421 self.lcm_tasks.register(
3422 "ns",
3423 nsr_id,
3424 nslcmop_id,
3425 "instantiate_N2VC-{}".format(vca_index),
3426 task_n2vc,
3427 )
3428 task_instantiation_info[
3429 task_n2vc
3430 ] = self.task_name_deploy_vca + " {}.{}".format(
3431 member_vnf_index or "", vdu_id or ""
3432 )
tiernobaa51102018-12-14 13:16:18 +00003433
tiernoc9556972019-07-05 15:25:25 +00003434 @staticmethod
kuuse0ca67472019-05-13 15:59:27 +02003435 def _create_nslcmop(nsr_id, operation, params):
3436 """
3437 Creates a ns-lcm-opp content to be stored at database.
3438 :param nsr_id: internal id of the instance
3439 :param operation: instantiate, terminate, scale, action, ...
3440 :param params: user parameters for the operation
3441 :return: dictionary following SOL005 format
3442 """
3443 # Raise exception if invalid arguments
3444 if not (nsr_id and operation and params):
3445 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01003446 "Parameters 'nsr_id', 'operation' and 'params' needed to create primitive not provided"
3447 )
kuuse0ca67472019-05-13 15:59:27 +02003448 now = time()
3449 _id = str(uuid4())
3450 nslcmop = {
3451 "id": _id,
3452 "_id": _id,
3453 # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
3454 "operationState": "PROCESSING",
3455 "statusEnteredTime": now,
3456 "nsInstanceId": nsr_id,
3457 "lcmOperationType": operation,
3458 "startTime": now,
3459 "isAutomaticInvocation": False,
3460 "operationParams": params,
3461 "isCancelPending": False,
3462 "links": {
3463 "self": "/osm/nslcm/v1/ns_lcm_op_occs/" + _id,
3464 "nsInstance": "/osm/nslcm/v1/ns_instances/" + nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01003465 },
kuuse0ca67472019-05-13 15:59:27 +02003466 }
3467 return nslcmop
3468
calvinosanch9f9c6f22019-11-04 13:37:39 +01003469 def _format_additional_params(self, params):
tierno626e0152019-11-29 14:16:16 +00003470 params = params or {}
calvinosanch9f9c6f22019-11-04 13:37:39 +01003471 for key, value in params.items():
3472 if str(value).startswith("!!yaml "):
3473 params[key] = yaml.safe_load(value[7:])
calvinosanch9f9c6f22019-11-04 13:37:39 +01003474 return params
3475
kuuse8b998e42019-07-30 15:22:16 +02003476 def _get_terminate_primitive_params(self, seq, vnf_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003477 primitive = seq.get("name")
kuuse8b998e42019-07-30 15:22:16 +02003478 primitive_params = {}
3479 params = {
3480 "member_vnf_index": vnf_index,
3481 "primitive": primitive,
3482 "primitive_params": primitive_params,
3483 }
3484 desc_params = {}
3485 return self._map_primitive_params(seq, params, desc_params)
3486
kuuseac3a8882019-10-03 10:48:06 +02003487 # sub-operations
3488
tierno51183952020-04-03 15:48:18 +00003489 def _retry_or_skip_suboperation(self, db_nslcmop, op_index):
garciadeblas5697b8b2021-03-24 09:17:02 +01003490 op = deep_get(db_nslcmop, ("_admin", "operations"), [])[op_index]
3491 if op.get("operationState") == "COMPLETED":
kuuseac3a8882019-10-03 10:48:06 +02003492 # b. Skip sub-operation
3493 # _ns_execute_primitive() or RO.create_action() will NOT be executed
3494 return self.SUBOPERATION_STATUS_SKIP
3495 else:
tierno7c4e24c2020-05-13 08:41:35 +00003496 # c. retry executing sub-operation
kuuseac3a8882019-10-03 10:48:06 +02003497 # The sub-operation exists, and operationState != 'COMPLETED'
tierno7c4e24c2020-05-13 08:41:35 +00003498 # Update operationState = 'PROCESSING' to indicate a retry.
garciadeblas5697b8b2021-03-24 09:17:02 +01003499 operationState = "PROCESSING"
3500 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003501 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01003502 db_nslcmop, op_index, operationState, detailed_status
3503 )
kuuseac3a8882019-10-03 10:48:06 +02003504 # Return the sub-operation index
3505 # _ns_execute_primitive() or RO.create_action() will be called from scale()
3506 # with arguments extracted from the sub-operation
3507 return op_index
3508
3509 # Find a sub-operation where all keys in a matching dictionary must match
3510 # Returns the index of the matching sub-operation, or SUBOPERATION_STATUS_NOT_FOUND if no match
3511 def _find_suboperation(self, db_nslcmop, match):
tierno7c4e24c2020-05-13 08:41:35 +00003512 if db_nslcmop and match:
garciadeblas5697b8b2021-03-24 09:17:02 +01003513 op_list = db_nslcmop.get("_admin", {}).get("operations", [])
kuuseac3a8882019-10-03 10:48:06 +02003514 for i, op in enumerate(op_list):
3515 if all(op.get(k) == match[k] for k in match):
3516 return i
3517 return self.SUBOPERATION_STATUS_NOT_FOUND
3518
3519 # Update status for a sub-operation given its index
garciadeblas5697b8b2021-03-24 09:17:02 +01003520 def _update_suboperation_status(
3521 self, db_nslcmop, op_index, operationState, detailed_status
3522 ):
kuuseac3a8882019-10-03 10:48:06 +02003523 # Update DB for HA tasks
garciadeblas5697b8b2021-03-24 09:17:02 +01003524 q_filter = {"_id": db_nslcmop["_id"]}
3525 update_dict = {
3526 "_admin.operations.{}.operationState".format(op_index): operationState,
3527 "_admin.operations.{}.detailed-status".format(op_index): detailed_status,
3528 }
3529 self.db.set_one(
3530 "nslcmops", q_filter=q_filter, update_dict=update_dict, fail_on_empty=False
3531 )
kuuseac3a8882019-10-03 10:48:06 +02003532
3533 # Add sub-operation, return the index of the added sub-operation
3534 # Optionally, set operationState, detailed-status, and operationType
3535 # Status and type are currently set for 'scale' sub-operations:
3536 # 'operationState' : 'PROCESSING' | 'COMPLETED' | 'FAILED'
3537 # 'detailed-status' : status message
3538 # 'operationType': may be any type, in the case of scaling: 'PRE-SCALE' | 'POST-SCALE'
3539 # Status and operation type are currently only used for 'scale', but NOT for 'terminate' sub-operations.
garciadeblas5697b8b2021-03-24 09:17:02 +01003540 def _add_suboperation(
3541 self,
3542 db_nslcmop,
3543 vnf_index,
3544 vdu_id,
3545 vdu_count_index,
3546 vdu_name,
3547 primitive,
3548 mapped_primitive_params,
3549 operationState=None,
3550 detailed_status=None,
3551 operationType=None,
3552 RO_nsr_id=None,
3553 RO_scaling_info=None,
3554 ):
tiernoe876f672020-02-13 14:34:48 +00003555 if not db_nslcmop:
kuuseac3a8882019-10-03 10:48:06 +02003556 return self.SUBOPERATION_STATUS_NOT_FOUND
3557 # Get the "_admin.operations" list, if it exists
garciadeblas5697b8b2021-03-24 09:17:02 +01003558 db_nslcmop_admin = db_nslcmop.get("_admin", {})
3559 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003560 # Create or append to the "_admin.operations" list
garciadeblas5697b8b2021-03-24 09:17:02 +01003561 new_op = {
3562 "member_vnf_index": vnf_index,
3563 "vdu_id": vdu_id,
3564 "vdu_count_index": vdu_count_index,
3565 "primitive": primitive,
3566 "primitive_params": mapped_primitive_params,
3567 }
kuuseac3a8882019-10-03 10:48:06 +02003568 if operationState:
garciadeblas5697b8b2021-03-24 09:17:02 +01003569 new_op["operationState"] = operationState
kuuseac3a8882019-10-03 10:48:06 +02003570 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01003571 new_op["detailed-status"] = detailed_status
kuuseac3a8882019-10-03 10:48:06 +02003572 if operationType:
garciadeblas5697b8b2021-03-24 09:17:02 +01003573 new_op["lcmOperationType"] = operationType
kuuseac3a8882019-10-03 10:48:06 +02003574 if RO_nsr_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01003575 new_op["RO_nsr_id"] = RO_nsr_id
kuuseac3a8882019-10-03 10:48:06 +02003576 if RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003577 new_op["RO_scaling_info"] = RO_scaling_info
kuuseac3a8882019-10-03 10:48:06 +02003578 if not op_list:
3579 # No existing operations, create key 'operations' with current operation as first list element
garciadeblas5697b8b2021-03-24 09:17:02 +01003580 db_nslcmop_admin.update({"operations": [new_op]})
3581 op_list = db_nslcmop_admin.get("operations")
kuuseac3a8882019-10-03 10:48:06 +02003582 else:
3583 # Existing operations, append operation to list
3584 op_list.append(new_op)
kuuse8b998e42019-07-30 15:22:16 +02003585
garciadeblas5697b8b2021-03-24 09:17:02 +01003586 db_nslcmop_update = {"_admin.operations": op_list}
3587 self.update_db_2("nslcmops", db_nslcmop["_id"], db_nslcmop_update)
kuuseac3a8882019-10-03 10:48:06 +02003588 op_index = len(op_list) - 1
3589 return op_index
3590
3591 # Helper methods for scale() sub-operations
3592
3593 # pre-scale/post-scale:
3594 # Check for 3 different cases:
3595 # a. New: First time execution, return SUBOPERATION_STATUS_NEW
3596 # b. Skip: Existing sub-operation exists, operationState == 'COMPLETED', return SUBOPERATION_STATUS_SKIP
tierno7c4e24c2020-05-13 08:41:35 +00003597 # c. retry: Existing sub-operation exists, operationState != 'COMPLETED', return op_index to re-execute
garciadeblas5697b8b2021-03-24 09:17:02 +01003598 def _check_or_add_scale_suboperation(
3599 self,
3600 db_nslcmop,
3601 vnf_index,
3602 vnf_config_primitive,
3603 primitive_params,
3604 operationType,
3605 RO_nsr_id=None,
3606 RO_scaling_info=None,
3607 ):
kuuseac3a8882019-10-03 10:48:06 +02003608 # Find this sub-operation
tierno7c4e24c2020-05-13 08:41:35 +00003609 if RO_nsr_id and RO_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01003610 operationType = "SCALE-RO"
kuuseac3a8882019-10-03 10:48:06 +02003611 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003612 "member_vnf_index": vnf_index,
3613 "RO_nsr_id": RO_nsr_id,
3614 "RO_scaling_info": RO_scaling_info,
kuuseac3a8882019-10-03 10:48:06 +02003615 }
3616 else:
3617 match = {
garciadeblas5697b8b2021-03-24 09:17:02 +01003618 "member_vnf_index": vnf_index,
3619 "primitive": vnf_config_primitive,
3620 "primitive_params": primitive_params,
3621 "lcmOperationType": operationType,
kuuseac3a8882019-10-03 10:48:06 +02003622 }
3623 op_index = self._find_suboperation(db_nslcmop, match)
tierno51183952020-04-03 15:48:18 +00003624 if op_index == self.SUBOPERATION_STATUS_NOT_FOUND:
kuuseac3a8882019-10-03 10:48:06 +02003625 # a. New sub-operation
3626 # The sub-operation does not exist, add it.
3627 # _ns_execute_primitive() will be called from scale() as usual, with non-modified arguments
3628 # The following parameters are set to None for all kind of scaling:
3629 vdu_id = None
3630 vdu_count_index = None
3631 vdu_name = None
tierno51183952020-04-03 15:48:18 +00003632 if RO_nsr_id and RO_scaling_info:
kuuseac3a8882019-10-03 10:48:06 +02003633 vnf_config_primitive = None
3634 primitive_params = None
3635 else:
3636 RO_nsr_id = None
3637 RO_scaling_info = None
3638 # Initial status for sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003639 operationState = "PROCESSING"
3640 detailed_status = "In progress"
kuuseac3a8882019-10-03 10:48:06 +02003641 # Add sub-operation for pre/post-scaling (zero or more operations)
garciadeblas5697b8b2021-03-24 09:17:02 +01003642 self._add_suboperation(
3643 db_nslcmop,
3644 vnf_index,
3645 vdu_id,
3646 vdu_count_index,
3647 vdu_name,
3648 vnf_config_primitive,
3649 primitive_params,
3650 operationState,
3651 detailed_status,
3652 operationType,
3653 RO_nsr_id,
3654 RO_scaling_info,
3655 )
kuuseac3a8882019-10-03 10:48:06 +02003656 return self.SUBOPERATION_STATUS_NEW
3657 else:
3658 # Return either SUBOPERATION_STATUS_SKIP (operationState == 'COMPLETED'),
3659 # or op_index (operationState != 'COMPLETED')
tierno51183952020-04-03 15:48:18 +00003660 return self._retry_or_skip_suboperation(db_nslcmop, op_index)
kuuseac3a8882019-10-03 10:48:06 +02003661
preethika.pdf7d8e02019-12-10 13:10:48 +00003662 # Function to return execution_environment id
3663
3664 def _get_ee_id(self, vnf_index, vdu_id, vca_deployed_list):
tiernoe876f672020-02-13 14:34:48 +00003665 # TODO vdu_index_count
preethika.pdf7d8e02019-12-10 13:10:48 +00003666 for vca in vca_deployed_list:
3667 if vca["member-vnf-index"] == vnf_index and vca["vdu_id"] == vdu_id:
3668 return vca["ee_id"]
3669
David Garciac1fe90a2021-03-31 19:12:02 +02003670 async def destroy_N2VC(
3671 self,
3672 logging_text,
3673 db_nslcmop,
3674 vca_deployed,
3675 config_descriptor,
3676 vca_index,
3677 destroy_ee=True,
3678 exec_primitives=True,
3679 scaling_in=False,
3680 vca_id: str = None,
3681 ):
tiernoe876f672020-02-13 14:34:48 +00003682 """
3683 Execute the terminate primitives and destroy the execution environment (if destroy_ee=False
3684 :param logging_text:
3685 :param db_nslcmop:
3686 :param vca_deployed: Dictionary of deployment info at db_nsr._admin.depoloyed.VCA.<INDEX>
3687 :param config_descriptor: Configuration descriptor of the NSD, VNFD, VNFD.vdu or VNFD.kdu
3688 :param vca_index: index in the database _admin.deployed.VCA
3689 :param destroy_ee: False to do not destroy, because it will be destroyed all of then at once
tierno588547c2020-07-01 15:30:20 +00003690 :param exec_primitives: False to do not execute terminate primitives, because the config is not completed or has
3691 not executed properly
aktas13251562021-02-12 22:19:10 +03003692 :param scaling_in: True destroys the application, False destroys the model
tiernoe876f672020-02-13 14:34:48 +00003693 :return: None or exception
3694 """
tiernoe876f672020-02-13 14:34:48 +00003695
tierno588547c2020-07-01 15:30:20 +00003696 self.logger.debug(
garciadeblas5697b8b2021-03-24 09:17:02 +01003697 logging_text
3698 + " vca_index: {}, vca_deployed: {}, config_descriptor: {}, destroy_ee: {}".format(
tierno588547c2020-07-01 15:30:20 +00003699 vca_index, vca_deployed, config_descriptor, destroy_ee
3700 )
3701 )
3702
3703 vca_type = vca_deployed.get("type", "lxc_proxy_charm")
3704
3705 # execute terminate_primitives
3706 if exec_primitives:
bravof922c4172020-11-24 21:21:43 -03003707 terminate_primitives = get_ee_sorted_terminate_config_primitive_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01003708 config_descriptor.get("terminate-config-primitive"),
3709 vca_deployed.get("ee_descriptor_id"),
3710 )
tierno588547c2020-07-01 15:30:20 +00003711 vdu_id = vca_deployed.get("vdu_id")
3712 vdu_count_index = vca_deployed.get("vdu_count_index")
3713 vdu_name = vca_deployed.get("vdu_name")
3714 vnf_index = vca_deployed.get("member-vnf-index")
3715 if terminate_primitives and vca_deployed.get("needed_terminate"):
tierno588547c2020-07-01 15:30:20 +00003716 for seq in terminate_primitives:
3717 # For each sequence in list, get primitive and call _ns_execute_primitive()
3718 step = "Calling terminate action for vnf_member_index={} primitive={}".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01003719 vnf_index, seq.get("name")
3720 )
tierno588547c2020-07-01 15:30:20 +00003721 self.logger.debug(logging_text + step)
3722 # Create the primitive for each sequence, i.e. "primitive": "touch"
garciadeblas5697b8b2021-03-24 09:17:02 +01003723 primitive = seq.get("name")
3724 mapped_primitive_params = self._get_terminate_primitive_params(
3725 seq, vnf_index
3726 )
tierno588547c2020-07-01 15:30:20 +00003727
3728 # Add sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01003729 self._add_suboperation(
3730 db_nslcmop,
3731 vnf_index,
3732 vdu_id,
3733 vdu_count_index,
3734 vdu_name,
3735 primitive,
3736 mapped_primitive_params,
3737 )
tierno588547c2020-07-01 15:30:20 +00003738 # Sub-operations: Call _ns_execute_primitive() instead of action()
3739 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003740 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01003741 vca_deployed["ee_id"],
3742 primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02003743 mapped_primitive_params,
3744 vca_type=vca_type,
3745 vca_id=vca_id,
3746 )
tierno588547c2020-07-01 15:30:20 +00003747 except LcmException:
3748 # this happens when VCA is not deployed. In this case it is not needed to terminate
3749 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01003750 result_ok = ["COMPLETED", "PARTIALLY_COMPLETED"]
tierno588547c2020-07-01 15:30:20 +00003751 if result not in result_ok:
garciadeblas5697b8b2021-03-24 09:17:02 +01003752 raise LcmException(
3753 "terminate_primitive {} for vnf_member_index={} fails with "
3754 "error {}".format(seq.get("name"), vnf_index, result_detail)
3755 )
tierno588547c2020-07-01 15:30:20 +00003756 # set that this VCA do not need terminated
garciadeblas5697b8b2021-03-24 09:17:02 +01003757 db_update_entry = "_admin.deployed.VCA.{}.needed_terminate".format(
3758 vca_index
3759 )
3760 self.update_db_2(
3761 "nsrs", db_nslcmop["nsInstanceId"], {db_update_entry: False}
3762 )
tiernoe876f672020-02-13 14:34:48 +00003763
tiernob996d942020-07-03 14:52:28 +00003764 if vca_deployed.get("prometheus_jobs") and self.prometheus:
3765 await self.prometheus.update(remove_jobs=vca_deployed["prometheus_jobs"])
3766
tiernoe876f672020-02-13 14:34:48 +00003767 if destroy_ee:
David Garciac1fe90a2021-03-31 19:12:02 +02003768 await self.vca_map[vca_type].delete_execution_environment(
3769 vca_deployed["ee_id"],
3770 scaling_in=scaling_in,
aktas730569b2021-07-29 17:42:49 +03003771 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02003772 vca_id=vca_id,
3773 )
kuuse0ca67472019-05-13 15:59:27 +02003774
David Garciac1fe90a2021-03-31 19:12:02 +02003775 async def _delete_all_N2VC(self, db_nsr: dict, vca_id: str = None):
garciadeblas5697b8b2021-03-24 09:17:02 +01003776 self._write_all_config_status(db_nsr=db_nsr, status="TERMINATING")
tierno51183952020-04-03 15:48:18 +00003777 namespace = "." + db_nsr["_id"]
tiernof59ad6c2020-04-08 12:50:52 +00003778 try:
David Garciac1fe90a2021-03-31 19:12:02 +02003779 await self.n2vc.delete_namespace(
3780 namespace=namespace,
3781 total_timeout=self.timeout_charm_delete,
3782 vca_id=vca_id,
3783 )
tiernof59ad6c2020-04-08 12:50:52 +00003784 except N2VCNotFound: # already deleted. Skip
3785 pass
garciadeblas5697b8b2021-03-24 09:17:02 +01003786 self._write_all_config_status(db_nsr=db_nsr, status="DELETED")
quilesj3655ae02019-12-12 16:08:35 +00003787
garciadeblas5697b8b2021-03-24 09:17:02 +01003788 async def _terminate_RO(
3789 self, logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
3790 ):
tiernoe876f672020-02-13 14:34:48 +00003791 """
3792 Terminates a deployment from RO
3793 :param logging_text:
3794 :param nsr_deployed: db_nsr._admin.deployed
3795 :param nsr_id:
3796 :param nslcmop_id:
3797 :param stage: list of string with the content to write on db_nslcmop.detailed-status.
3798 this method will update only the index 2, but it will write on database the concatenated content of the list
3799 :return:
3800 """
3801 db_nsr_update = {}
3802 failed_detail = []
3803 ro_nsr_id = ro_delete_action = None
3804 if nsr_deployed and nsr_deployed.get("RO"):
3805 ro_nsr_id = nsr_deployed["RO"].get("nsr_id")
3806 ro_delete_action = nsr_deployed["RO"].get("nsr_delete_action_id")
3807 try:
3808 if ro_nsr_id:
3809 stage[2] = "Deleting ns from VIM."
3810 db_nsr_update["detailed-status"] = " ".join(stage)
3811 self._write_op_status(nslcmop_id, stage)
3812 self.logger.debug(logging_text + stage[2])
3813 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3814 self._write_op_status(nslcmop_id, stage)
3815 desc = await self.RO.delete("ns", ro_nsr_id)
3816 ro_delete_action = desc["action_id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003817 db_nsr_update[
3818 "_admin.deployed.RO.nsr_delete_action_id"
3819 ] = ro_delete_action
tiernoe876f672020-02-13 14:34:48 +00003820 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3821 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3822 if ro_delete_action:
3823 # wait until NS is deleted from VIM
3824 stage[2] = "Waiting ns deleted from VIM."
3825 detailed_status_old = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003826 self.logger.debug(
3827 logging_text
3828 + stage[2]
3829 + " RO_id={} ro_delete_action={}".format(
3830 ro_nsr_id, ro_delete_action
3831 )
3832 )
tiernoe876f672020-02-13 14:34:48 +00003833 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3834 self._write_op_status(nslcmop_id, stage)
kuused124bfe2019-06-18 12:09:24 +02003835
tiernoe876f672020-02-13 14:34:48 +00003836 delete_timeout = 20 * 60 # 20 minutes
3837 while delete_timeout > 0:
3838 desc = await self.RO.show(
3839 "ns",
3840 item_id_name=ro_nsr_id,
3841 extra_item="action",
garciadeblas5697b8b2021-03-24 09:17:02 +01003842 extra_item_id=ro_delete_action,
3843 )
tiernoe876f672020-02-13 14:34:48 +00003844
3845 # deploymentStatus
3846 self._on_update_ro_db(nsrs_id=nsr_id, ro_descriptor=desc)
3847
3848 ns_status, ns_status_info = self.RO.check_action_status(desc)
3849 if ns_status == "ERROR":
3850 raise ROclient.ROClientException(ns_status_info)
3851 elif ns_status == "BUILD":
3852 stage[2] = "Deleting from VIM {}".format(ns_status_info)
3853 elif ns_status == "ACTIVE":
3854 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
3855 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3856 break
3857 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003858 assert (
3859 False
3860 ), "ROclient.check_action_status returns unknown {}".format(
3861 ns_status
3862 )
tiernoe876f672020-02-13 14:34:48 +00003863 if stage[2] != detailed_status_old:
3864 detailed_status_old = stage[2]
3865 db_nsr_update["detailed-status"] = " ".join(stage)
3866 self._write_op_status(nslcmop_id, stage)
3867 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3868 await asyncio.sleep(5, loop=self.loop)
3869 delete_timeout -= 5
3870 else: # delete_timeout <= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01003871 raise ROclient.ROClientException(
3872 "Timeout waiting ns deleted from VIM"
3873 )
tiernoe876f672020-02-13 14:34:48 +00003874
3875 except Exception as e:
3876 self.update_db_2("nsrs", nsr_id, db_nsr_update)
garciadeblas5697b8b2021-03-24 09:17:02 +01003877 if (
3878 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3879 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003880 db_nsr_update["_admin.deployed.RO.nsr_id"] = None
3881 db_nsr_update["_admin.deployed.RO.nsr_status"] = "DELETED"
3882 db_nsr_update["_admin.deployed.RO.nsr_delete_action_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003883 self.logger.debug(
3884 logging_text + "RO_ns_id={} already deleted".format(ro_nsr_id)
3885 )
3886 elif (
3887 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3888 ): # conflict
tiernoa2143262020-03-27 16:20:40 +00003889 failed_detail.append("delete conflict: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003890 self.logger.debug(
3891 logging_text
3892 + "RO_ns_id={} delete conflict: {}".format(ro_nsr_id, e)
3893 )
tiernoe876f672020-02-13 14:34:48 +00003894 else:
tiernoa2143262020-03-27 16:20:40 +00003895 failed_detail.append("delete error: {}".format(e))
garciadeblas5697b8b2021-03-24 09:17:02 +01003896 self.logger.error(
3897 logging_text + "RO_ns_id={} delete error: {}".format(ro_nsr_id, e)
3898 )
tiernoe876f672020-02-13 14:34:48 +00003899
3900 # Delete nsd
3901 if not failed_detail and deep_get(nsr_deployed, ("RO", "nsd_id")):
3902 ro_nsd_id = nsr_deployed["RO"]["nsd_id"]
3903 try:
3904 stage[2] = "Deleting nsd from RO."
3905 db_nsr_update["detailed-status"] = " ".join(stage)
3906 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3907 self._write_op_status(nslcmop_id, stage)
3908 await self.RO.delete("nsd", ro_nsd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01003909 self.logger.debug(
3910 logging_text + "ro_nsd_id={} deleted".format(ro_nsd_id)
3911 )
tiernoe876f672020-02-13 14:34:48 +00003912 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
3913 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003914 if (
3915 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3916 ): # not found
tiernoe876f672020-02-13 14:34:48 +00003917 db_nsr_update["_admin.deployed.RO.nsd_id"] = None
garciadeblas5697b8b2021-03-24 09:17:02 +01003918 self.logger.debug(
3919 logging_text + "ro_nsd_id={} already deleted".format(ro_nsd_id)
3920 )
3921 elif (
3922 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3923 ): # conflict
3924 failed_detail.append(
3925 "ro_nsd_id={} delete conflict: {}".format(ro_nsd_id, e)
3926 )
tiernoe876f672020-02-13 14:34:48 +00003927 self.logger.debug(logging_text + failed_detail[-1])
3928 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003929 failed_detail.append(
3930 "ro_nsd_id={} delete error: {}".format(ro_nsd_id, e)
3931 )
tiernoe876f672020-02-13 14:34:48 +00003932 self.logger.error(logging_text + failed_detail[-1])
3933
3934 if not failed_detail and deep_get(nsr_deployed, ("RO", "vnfd")):
3935 for index, vnf_deployed in enumerate(nsr_deployed["RO"]["vnfd"]):
3936 if not vnf_deployed or not vnf_deployed["id"]:
3937 continue
3938 try:
3939 ro_vnfd_id = vnf_deployed["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01003940 stage[
3941 2
3942 ] = "Deleting member_vnf_index={} ro_vnfd_id={} from RO.".format(
3943 vnf_deployed["member-vnf-index"], ro_vnfd_id
3944 )
tiernoe876f672020-02-13 14:34:48 +00003945 db_nsr_update["detailed-status"] = " ".join(stage)
3946 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3947 self._write_op_status(nslcmop_id, stage)
3948 await self.RO.delete("vnfd", ro_vnfd_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01003949 self.logger.debug(
3950 logging_text + "ro_vnfd_id={} deleted".format(ro_vnfd_id)
3951 )
tiernoe876f672020-02-13 14:34:48 +00003952 db_nsr_update["_admin.deployed.RO.vnfd.{}.id".format(index)] = None
3953 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01003954 if (
3955 isinstance(e, ROclient.ROClientException) and e.http_code == 404
3956 ): # not found
3957 db_nsr_update[
3958 "_admin.deployed.RO.vnfd.{}.id".format(index)
3959 ] = None
3960 self.logger.debug(
3961 logging_text
3962 + "ro_vnfd_id={} already deleted ".format(ro_vnfd_id)
3963 )
3964 elif (
3965 isinstance(e, ROclient.ROClientException) and e.http_code == 409
3966 ): # conflict
3967 failed_detail.append(
3968 "ro_vnfd_id={} delete conflict: {}".format(ro_vnfd_id, e)
3969 )
tiernoe876f672020-02-13 14:34:48 +00003970 self.logger.debug(logging_text + failed_detail[-1])
3971 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01003972 failed_detail.append(
3973 "ro_vnfd_id={} delete error: {}".format(ro_vnfd_id, e)
3974 )
tiernoe876f672020-02-13 14:34:48 +00003975 self.logger.error(logging_text + failed_detail[-1])
3976
tiernoa2143262020-03-27 16:20:40 +00003977 if failed_detail:
3978 stage[2] = "Error deleting from VIM"
3979 else:
3980 stage[2] = "Deleted from VIM"
tiernoe876f672020-02-13 14:34:48 +00003981 db_nsr_update["detailed-status"] = " ".join(stage)
3982 self.update_db_2("nsrs", nsr_id, db_nsr_update)
3983 self._write_op_status(nslcmop_id, stage)
3984
3985 if failed_detail:
tiernoa2143262020-03-27 16:20:40 +00003986 raise LcmException("; ".join(failed_detail))
tiernoe876f672020-02-13 14:34:48 +00003987
3988 async def terminate(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02003989 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01003990 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02003991 if not task_is_locked_by_me:
3992 return
3993
tierno59d22d22018-09-25 18:10:19 +02003994 logging_text = "Task ns={} terminate={} ".format(nsr_id, nslcmop_id)
3995 self.logger.debug(logging_text + "Enter")
tiernoe876f672020-02-13 14:34:48 +00003996 timeout_ns_terminate = self.timeout_ns_terminate
tierno59d22d22018-09-25 18:10:19 +02003997 db_nsr = None
3998 db_nslcmop = None
tiernoa17d4f42020-04-28 09:59:23 +00003999 operation_params = None
tierno59d22d22018-09-25 18:10:19 +02004000 exc = None
garciadeblas5697b8b2021-03-24 09:17:02 +01004001 error_list = [] # annotates all failed error messages
tierno59d22d22018-09-25 18:10:19 +02004002 db_nslcmop_update = {}
tiernoc2564fe2019-01-28 16:18:56 +00004003 autoremove = False # autoremove after terminated
tiernoe876f672020-02-13 14:34:48 +00004004 tasks_dict_info = {}
4005 db_nsr_update = {}
garciadeblas5697b8b2021-03-24 09:17:02 +01004006 stage = [
4007 "Stage 1/3: Preparing task.",
4008 "Waiting for previous operations to terminate.",
4009 "",
4010 ]
tiernoe876f672020-02-13 14:34:48 +00004011 # ^ contains [stage, step, VIM-status]
tierno59d22d22018-09-25 18:10:19 +02004012 try:
kuused124bfe2019-06-18 12:09:24 +02004013 # wait for any previous tasks in process
garciadeblas5697b8b2021-03-24 09:17:02 +01004014 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004015
tiernoe876f672020-02-13 14:34:48 +00004016 stage[1] = "Getting nslcmop={} from db.".format(nslcmop_id)
4017 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4018 operation_params = db_nslcmop.get("operationParams") or {}
4019 if operation_params.get("timeout_ns_terminate"):
4020 timeout_ns_terminate = operation_params["timeout_ns_terminate"]
4021 stage[1] = "Getting nsr={} from db.".format(nsr_id)
4022 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
4023
4024 db_nsr_update["operational-status"] = "terminating"
4025 db_nsr_update["config-status"] = "terminating"
quilesj4cda56b2019-12-05 10:02:20 +00004026 self._write_ns_status(
4027 nsr_id=nsr_id,
4028 ns_state="TERMINATING",
4029 current_operation="TERMINATING",
tiernoe876f672020-02-13 14:34:48 +00004030 current_operation_id=nslcmop_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004031 other_update=db_nsr_update,
quilesj4cda56b2019-12-05 10:02:20 +00004032 )
garciadeblas5697b8b2021-03-24 09:17:02 +01004033 self._write_op_status(op_id=nslcmop_id, queuePosition=0, stage=stage)
tiernoe876f672020-02-13 14:34:48 +00004034 nsr_deployed = deepcopy(db_nsr["_admin"].get("deployed")) or {}
tierno59d22d22018-09-25 18:10:19 +02004035 if db_nsr["_admin"]["nsState"] == "NOT_INSTANTIATED":
4036 return
tierno59d22d22018-09-25 18:10:19 +02004037
tiernoe876f672020-02-13 14:34:48 +00004038 stage[1] = "Getting vnf descriptors from db."
4039 db_vnfrs_list = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
garciadeblas5697b8b2021-03-24 09:17:02 +01004040 db_vnfrs_dict = {
4041 db_vnfr["member-vnf-index-ref"]: db_vnfr for db_vnfr in db_vnfrs_list
4042 }
tiernoe876f672020-02-13 14:34:48 +00004043 db_vnfds_from_id = {}
4044 db_vnfds_from_member_index = {}
4045 # Loop over VNFRs
4046 for vnfr in db_vnfrs_list:
4047 vnfd_id = vnfr["vnfd-id"]
4048 if vnfd_id not in db_vnfds_from_id:
4049 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
4050 db_vnfds_from_id[vnfd_id] = vnfd
garciadeblas5697b8b2021-03-24 09:17:02 +01004051 db_vnfds_from_member_index[
4052 vnfr["member-vnf-index-ref"]
4053 ] = db_vnfds_from_id[vnfd_id]
calvinosanch9f9c6f22019-11-04 13:37:39 +01004054
tiernoe876f672020-02-13 14:34:48 +00004055 # Destroy individual execution environments when there are terminating primitives.
4056 # Rest of EE will be deleted at once
tierno588547c2020-07-01 15:30:20 +00004057 # TODO - check before calling _destroy_N2VC
4058 # if not operation_params.get("skip_terminate_primitives"):#
4059 # or not vca.get("needed_terminate"):
4060 stage[0] = "Stage 2/3 execute terminating primitives."
4061 self.logger.debug(logging_text + stage[0])
4062 stage[1] = "Looking execution environment that needs terminate."
4063 self.logger.debug(logging_text + stage[1])
bravof922c4172020-11-24 21:21:43 -03004064
tierno588547c2020-07-01 15:30:20 +00004065 for vca_index, vca in enumerate(get_iterable(nsr_deployed, "VCA")):
tierno588547c2020-07-01 15:30:20 +00004066 config_descriptor = None
David Garciab76442a2021-05-28 12:08:18 +02004067 vca_member_vnf_index = vca.get("member-vnf-index")
4068 vca_id = self.get_vca_id(
4069 db_vnfrs_dict.get(vca_member_vnf_index)
4070 if vca_member_vnf_index
4071 else None,
4072 db_nsr,
4073 )
tierno588547c2020-07-01 15:30:20 +00004074 if not vca or not vca.get("ee_id"):
4075 continue
4076 if not vca.get("member-vnf-index"):
4077 # ns
4078 config_descriptor = db_nsr.get("ns-configuration")
4079 elif vca.get("vdu_id"):
4080 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004081 config_descriptor = get_configuration(db_vnfd, vca.get("vdu_id"))
tierno588547c2020-07-01 15:30:20 +00004082 elif vca.get("kdu_name"):
4083 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
bravofe5a31bc2021-02-17 19:09:12 -03004084 config_descriptor = get_configuration(db_vnfd, vca.get("kdu_name"))
tierno588547c2020-07-01 15:30:20 +00004085 else:
bravofe5a31bc2021-02-17 19:09:12 -03004086 db_vnfd = db_vnfds_from_member_index[vca["member-vnf-index"]]
aktas13251562021-02-12 22:19:10 +03004087 config_descriptor = get_configuration(db_vnfd, db_vnfd["id"])
tierno588547c2020-07-01 15:30:20 +00004088 vca_type = vca.get("type")
garciadeblas5697b8b2021-03-24 09:17:02 +01004089 exec_terminate_primitives = not operation_params.get(
4090 "skip_terminate_primitives"
4091 ) and vca.get("needed_terminate")
tiernoaebd7da2020-08-07 06:36:38 +00004092 # For helm we must destroy_ee. Also for native_charm, as juju_model cannot be deleted if there are
4093 # pending native charms
garciadeblas5697b8b2021-03-24 09:17:02 +01004094 destroy_ee = (
4095 True if vca_type in ("helm", "helm-v3", "native_charm") else False
4096 )
tierno86e33612020-09-16 14:13:06 +00004097 # self.logger.debug(logging_text + "vca_index: {}, ee_id: {}, vca_type: {} destroy_ee: {}".format(
4098 # vca_index, vca.get("ee_id"), vca_type, destroy_ee))
tiernob996d942020-07-03 14:52:28 +00004099 task = asyncio.ensure_future(
David Garciac1fe90a2021-03-31 19:12:02 +02004100 self.destroy_N2VC(
4101 logging_text,
4102 db_nslcmop,
4103 vca,
4104 config_descriptor,
4105 vca_index,
4106 destroy_ee,
4107 exec_terminate_primitives,
4108 vca_id=vca_id,
4109 )
4110 )
tierno588547c2020-07-01 15:30:20 +00004111 tasks_dict_info[task] = "Terminating VCA {}".format(vca.get("ee_id"))
tierno59d22d22018-09-25 18:10:19 +02004112
tierno588547c2020-07-01 15:30:20 +00004113 # wait for pending tasks of terminate primitives
4114 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01004115 self.logger.debug(
4116 logging_text
4117 + "Waiting for tasks {}".format(list(tasks_dict_info.keys()))
4118 )
4119 error_list = await self._wait_for_tasks(
4120 logging_text,
4121 tasks_dict_info,
4122 min(self.timeout_charm_delete, timeout_ns_terminate),
4123 stage,
4124 nslcmop_id,
4125 )
tierno86e33612020-09-16 14:13:06 +00004126 tasks_dict_info.clear()
tierno588547c2020-07-01 15:30:20 +00004127 if error_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01004128 return # raise LcmException("; ".join(error_list))
tierno82974b22018-11-27 21:55:36 +00004129
tiernoe876f672020-02-13 14:34:48 +00004130 # remove All execution environments at once
4131 stage[0] = "Stage 3/3 delete all."
quilesj3655ae02019-12-12 16:08:35 +00004132
tierno49676be2020-04-07 16:34:35 +00004133 if nsr_deployed.get("VCA"):
4134 stage[1] = "Deleting all execution environments."
4135 self.logger.debug(logging_text + stage[1])
David Garciac1fe90a2021-03-31 19:12:02 +02004136 vca_id = self.get_vca_id({}, db_nsr)
4137 task_delete_ee = asyncio.ensure_future(
4138 asyncio.wait_for(
4139 self._delete_all_N2VC(db_nsr=db_nsr, vca_id=vca_id),
garciadeblas5697b8b2021-03-24 09:17:02 +01004140 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02004141 )
4142 )
tierno49676be2020-04-07 16:34:35 +00004143 # task_delete_ee = asyncio.ensure_future(self.n2vc.delete_namespace(namespace="." + nsr_id))
4144 tasks_dict_info[task_delete_ee] = "Terminating all VCA"
tierno59d22d22018-09-25 18:10:19 +02004145
tiernoe876f672020-02-13 14:34:48 +00004146 # Delete from k8scluster
4147 stage[1] = "Deleting KDUs."
4148 self.logger.debug(logging_text + stage[1])
4149 # print(nsr_deployed)
4150 for kdu in get_iterable(nsr_deployed, "K8s"):
4151 if not kdu or not kdu.get("kdu-instance"):
4152 continue
4153 kdu_instance = kdu.get("kdu-instance")
tiernoa2143262020-03-27 16:20:40 +00004154 if kdu.get("k8scluster-type") in self.k8scluster_map:
David Garciac1fe90a2021-03-31 19:12:02 +02004155 # TODO: Uninstall kdu instances taking into account they could be deployed in different VIMs
4156 vca_id = self.get_vca_id({}, db_nsr)
tiernoe876f672020-02-13 14:34:48 +00004157 task_delete_kdu_instance = asyncio.ensure_future(
tiernoa2143262020-03-27 16:20:40 +00004158 self.k8scluster_map[kdu["k8scluster-type"]].uninstall(
4159 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004160 kdu_instance=kdu_instance,
4161 vca_id=vca_id,
4162 )
4163 )
tiernoe876f672020-02-13 14:34:48 +00004164 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004165 self.logger.error(
4166 logging_text
4167 + "Unknown k8s deployment type {}".format(
4168 kdu.get("k8scluster-type")
4169 )
4170 )
tiernoe876f672020-02-13 14:34:48 +00004171 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004172 tasks_dict_info[
4173 task_delete_kdu_instance
4174 ] = "Terminating KDU '{}'".format(kdu.get("kdu-name"))
tierno59d22d22018-09-25 18:10:19 +02004175
4176 # remove from RO
tiernoe876f672020-02-13 14:34:48 +00004177 stage[1] = "Deleting ns from VIM."
tierno69f0d382020-05-07 13:08:09 +00004178 if self.ng_ro:
4179 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004180 self._terminate_ng_ro(
4181 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4182 )
4183 )
tierno69f0d382020-05-07 13:08:09 +00004184 else:
4185 task_delete_ro = asyncio.ensure_future(
garciadeblas5697b8b2021-03-24 09:17:02 +01004186 self._terminate_RO(
4187 logging_text, nsr_deployed, nsr_id, nslcmop_id, stage
4188 )
4189 )
tiernoe876f672020-02-13 14:34:48 +00004190 tasks_dict_info[task_delete_ro] = "Removing deployment from VIM"
tierno59d22d22018-09-25 18:10:19 +02004191
tiernoe876f672020-02-13 14:34:48 +00004192 # rest of staff will be done at finally
4193
garciadeblas5697b8b2021-03-24 09:17:02 +01004194 except (
4195 ROclient.ROClientException,
4196 DbException,
4197 LcmException,
4198 N2VCException,
4199 ) as e:
tiernoe876f672020-02-13 14:34:48 +00004200 self.logger.error(logging_text + "Exit Exception {}".format(e))
4201 exc = e
4202 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004203 self.logger.error(
4204 logging_text + "Cancelled Exception while '{}'".format(stage[1])
4205 )
tiernoe876f672020-02-13 14:34:48 +00004206 exc = "Operation was cancelled"
4207 except Exception as e:
4208 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004209 self.logger.critical(
4210 logging_text + "Exit Exception while '{}': {}".format(stage[1], e),
4211 exc_info=True,
4212 )
tiernoe876f672020-02-13 14:34:48 +00004213 finally:
4214 if exc:
4215 error_list.append(str(exc))
tierno59d22d22018-09-25 18:10:19 +02004216 try:
tiernoe876f672020-02-13 14:34:48 +00004217 # wait for pending tasks
4218 if tasks_dict_info:
4219 stage[1] = "Waiting for terminate pending tasks."
4220 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01004221 error_list += await self._wait_for_tasks(
4222 logging_text,
4223 tasks_dict_info,
4224 timeout_ns_terminate,
4225 stage,
4226 nslcmop_id,
4227 )
tiernoe876f672020-02-13 14:34:48 +00004228 stage[1] = stage[2] = ""
4229 except asyncio.CancelledError:
4230 error_list.append("Cancelled")
4231 # TODO cancell all tasks
4232 except Exception as exc:
4233 error_list.append(str(exc))
4234 # update status at database
4235 if error_list:
4236 error_detail = "; ".join(error_list)
4237 # self.logger.error(logging_text + error_detail)
garciadeblas5697b8b2021-03-24 09:17:02 +01004238 error_description_nslcmop = "{} Detail: {}".format(
4239 stage[0], error_detail
4240 )
4241 error_description_nsr = "Operation: TERMINATING.{}, {}.".format(
4242 nslcmop_id, stage[0]
4243 )
tierno59d22d22018-09-25 18:10:19 +02004244
tierno59d22d22018-09-25 18:10:19 +02004245 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01004246 db_nsr_update["detailed-status"] = (
4247 error_description_nsr + " Detail: " + error_detail
4248 )
tiernoe876f672020-02-13 14:34:48 +00004249 db_nslcmop_update["detailed-status"] = error_detail
4250 nslcmop_operation_state = "FAILED"
4251 ns_state = "BROKEN"
tierno59d22d22018-09-25 18:10:19 +02004252 else:
tiernoa2143262020-03-27 16:20:40 +00004253 error_detail = None
tiernoe876f672020-02-13 14:34:48 +00004254 error_description_nsr = error_description_nslcmop = None
4255 ns_state = "NOT_INSTANTIATED"
tierno59d22d22018-09-25 18:10:19 +02004256 db_nsr_update["operational-status"] = "terminated"
4257 db_nsr_update["detailed-status"] = "Done"
4258 db_nsr_update["_admin.nsState"] = "NOT_INSTANTIATED"
4259 db_nslcmop_update["detailed-status"] = "Done"
tiernoe876f672020-02-13 14:34:48 +00004260 nslcmop_operation_state = "COMPLETED"
tierno59d22d22018-09-25 18:10:19 +02004261
tiernoe876f672020-02-13 14:34:48 +00004262 if db_nsr:
4263 self._write_ns_status(
4264 nsr_id=nsr_id,
4265 ns_state=ns_state,
4266 current_operation="IDLE",
4267 current_operation_id=None,
4268 error_description=error_description_nsr,
tiernoa2143262020-03-27 16:20:40 +00004269 error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004270 other_update=db_nsr_update,
tiernoe876f672020-02-13 14:34:48 +00004271 )
tiernoa17d4f42020-04-28 09:59:23 +00004272 self._write_op_status(
4273 op_id=nslcmop_id,
4274 stage="",
4275 error_message=error_description_nslcmop,
4276 operation_state=nslcmop_operation_state,
4277 other_update=db_nslcmop_update,
4278 )
lloretgalleg6d488782020-07-22 10:13:46 +00004279 if ns_state == "NOT_INSTANTIATED":
4280 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004281 self.db.set_list(
4282 "vnfrs",
4283 {"nsr-id-ref": nsr_id},
4284 {"_admin.nsState": "NOT_INSTANTIATED"},
4285 )
lloretgalleg6d488782020-07-22 10:13:46 +00004286 except DbException as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004287 self.logger.warn(
4288 logging_text
4289 + "Error writing VNFR status for nsr-id-ref: {} -> {}".format(
4290 nsr_id, e
4291 )
4292 )
tiernoa17d4f42020-04-28 09:59:23 +00004293 if operation_params:
tiernoe876f672020-02-13 14:34:48 +00004294 autoremove = operation_params.get("autoremove", False)
tierno59d22d22018-09-25 18:10:19 +02004295 if nslcmop_operation_state:
4296 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004297 await self.msg.aiowrite(
4298 "ns",
4299 "terminated",
4300 {
4301 "nsr_id": nsr_id,
4302 "nslcmop_id": nslcmop_id,
4303 "operationState": nslcmop_operation_state,
4304 "autoremove": autoremove,
4305 },
4306 loop=self.loop,
4307 )
tierno59d22d22018-09-25 18:10:19 +02004308 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004309 self.logger.error(
4310 logging_text + "kafka_write notification Exception {}".format(e)
4311 )
quilesj7e13aeb2019-10-08 13:34:55 +02004312
tierno59d22d22018-09-25 18:10:19 +02004313 self.logger.debug(logging_text + "Exit")
4314 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_terminate")
4315
garciadeblas5697b8b2021-03-24 09:17:02 +01004316 async def _wait_for_tasks(
4317 self, logging_text, created_tasks_info, timeout, stage, nslcmop_id, nsr_id=None
4318 ):
tiernoe876f672020-02-13 14:34:48 +00004319 time_start = time()
tiernoa2143262020-03-27 16:20:40 +00004320 error_detail_list = []
tiernoe876f672020-02-13 14:34:48 +00004321 error_list = []
4322 pending_tasks = list(created_tasks_info.keys())
4323 num_tasks = len(pending_tasks)
4324 num_done = 0
4325 stage[1] = "{}/{}.".format(num_done, num_tasks)
4326 self._write_op_status(nslcmop_id, stage)
tiernoe876f672020-02-13 14:34:48 +00004327 while pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004328 new_error = None
tiernoe876f672020-02-13 14:34:48 +00004329 _timeout = timeout + time_start - time()
garciadeblas5697b8b2021-03-24 09:17:02 +01004330 done, pending_tasks = await asyncio.wait(
4331 pending_tasks, timeout=_timeout, return_when=asyncio.FIRST_COMPLETED
4332 )
tiernoe876f672020-02-13 14:34:48 +00004333 num_done += len(done)
garciadeblas5697b8b2021-03-24 09:17:02 +01004334 if not done: # Timeout
tiernoe876f672020-02-13 14:34:48 +00004335 for task in pending_tasks:
tiernoa2143262020-03-27 16:20:40 +00004336 new_error = created_tasks_info[task] + ": Timeout"
4337 error_detail_list.append(new_error)
4338 error_list.append(new_error)
tiernoe876f672020-02-13 14:34:48 +00004339 break
4340 for task in done:
4341 if task.cancelled():
tierno067e04a2020-03-31 12:53:13 +00004342 exc = "Cancelled"
tiernoe876f672020-02-13 14:34:48 +00004343 else:
4344 exc = task.exception()
tierno067e04a2020-03-31 12:53:13 +00004345 if exc:
4346 if isinstance(exc, asyncio.TimeoutError):
4347 exc = "Timeout"
4348 new_error = created_tasks_info[task] + ": {}".format(exc)
4349 error_list.append(created_tasks_info[task])
4350 error_detail_list.append(new_error)
garciadeblas5697b8b2021-03-24 09:17:02 +01004351 if isinstance(
4352 exc,
4353 (
4354 str,
4355 DbException,
4356 N2VCException,
4357 ROclient.ROClientException,
4358 LcmException,
4359 K8sException,
4360 NgRoException,
4361 ),
4362 ):
tierno067e04a2020-03-31 12:53:13 +00004363 self.logger.error(logging_text + new_error)
tiernoe876f672020-02-13 14:34:48 +00004364 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004365 exc_traceback = "".join(
4366 traceback.format_exception(None, exc, exc.__traceback__)
4367 )
4368 self.logger.error(
4369 logging_text
4370 + created_tasks_info[task]
4371 + " "
4372 + exc_traceback
4373 )
tierno067e04a2020-03-31 12:53:13 +00004374 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004375 self.logger.debug(
4376 logging_text + created_tasks_info[task] + ": Done"
4377 )
tiernoe876f672020-02-13 14:34:48 +00004378 stage[1] = "{}/{}.".format(num_done, num_tasks)
4379 if new_error:
tiernoa2143262020-03-27 16:20:40 +00004380 stage[1] += " Errors: " + ". ".join(error_detail_list) + "."
tiernoe876f672020-02-13 14:34:48 +00004381 if nsr_id: # update also nsr
garciadeblas5697b8b2021-03-24 09:17:02 +01004382 self.update_db_2(
4383 "nsrs",
4384 nsr_id,
4385 {
4386 "errorDescription": "Error at: " + ", ".join(error_list),
4387 "errorDetail": ". ".join(error_detail_list),
4388 },
4389 )
tiernoe876f672020-02-13 14:34:48 +00004390 self._write_op_status(nslcmop_id, stage)
tiernoa2143262020-03-27 16:20:40 +00004391 return error_detail_list
tiernoe876f672020-02-13 14:34:48 +00004392
tiernoda1ff8c2020-10-22 14:12:46 +00004393 @staticmethod
4394 def _map_primitive_params(primitive_desc, params, instantiation_params):
tiernoda964822019-01-14 15:53:47 +00004395 """
4396 Generates the params to be provided to charm before executing primitive. If user does not provide a parameter,
4397 The default-value is used. If it is between < > it look for a value at instantiation_params
4398 :param primitive_desc: portion of VNFD/NSD that describes primitive
4399 :param params: Params provided by user
4400 :param instantiation_params: Instantiation params provided by user
4401 :return: a dictionary with the calculated params
4402 """
4403 calculated_params = {}
4404 for parameter in primitive_desc.get("parameter", ()):
4405 param_name = parameter["name"]
4406 if param_name in params:
4407 calculated_params[param_name] = params[param_name]
tierno98ad6ea2019-05-30 17:16:28 +00004408 elif "default-value" in parameter or "value" in parameter:
4409 if "value" in parameter:
4410 calculated_params[param_name] = parameter["value"]
4411 else:
4412 calculated_params[param_name] = parameter["default-value"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004413 if (
4414 isinstance(calculated_params[param_name], str)
4415 and calculated_params[param_name].startswith("<")
4416 and calculated_params[param_name].endswith(">")
4417 ):
tierno98ad6ea2019-05-30 17:16:28 +00004418 if calculated_params[param_name][1:-1] in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004419 calculated_params[param_name] = instantiation_params[
4420 calculated_params[param_name][1:-1]
4421 ]
tiernoda964822019-01-14 15:53:47 +00004422 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004423 raise LcmException(
4424 "Parameter {} needed to execute primitive {} not provided".format(
4425 calculated_params[param_name], primitive_desc["name"]
4426 )
4427 )
tiernoda964822019-01-14 15:53:47 +00004428 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004429 raise LcmException(
4430 "Parameter {} needed to execute primitive {} not provided".format(
4431 param_name, primitive_desc["name"]
4432 )
4433 )
tierno59d22d22018-09-25 18:10:19 +02004434
tiernoda964822019-01-14 15:53:47 +00004435 if isinstance(calculated_params[param_name], (dict, list, tuple)):
garciadeblas5697b8b2021-03-24 09:17:02 +01004436 calculated_params[param_name] = yaml.safe_dump(
4437 calculated_params[param_name], default_flow_style=True, width=256
4438 )
4439 elif isinstance(calculated_params[param_name], str) and calculated_params[
4440 param_name
4441 ].startswith("!!yaml "):
tiernoda964822019-01-14 15:53:47 +00004442 calculated_params[param_name] = calculated_params[param_name][7:]
tiernofa40e692020-10-14 14:59:36 +00004443 if parameter.get("data-type") == "INTEGER":
4444 try:
4445 calculated_params[param_name] = int(calculated_params[param_name])
4446 except ValueError: # error converting string to int
4447 raise LcmException(
garciadeblas5697b8b2021-03-24 09:17:02 +01004448 "Parameter {} of primitive {} must be integer".format(
4449 param_name, primitive_desc["name"]
4450 )
4451 )
tiernofa40e692020-10-14 14:59:36 +00004452 elif parameter.get("data-type") == "BOOLEAN":
garciadeblas5697b8b2021-03-24 09:17:02 +01004453 calculated_params[param_name] = not (
4454 (str(calculated_params[param_name])).lower() == "false"
4455 )
tiernoc3f2a822019-11-05 13:45:04 +00004456
4457 # add always ns_config_info if primitive name is config
4458 if primitive_desc["name"] == "config":
4459 if "ns_config_info" in instantiation_params:
garciadeblas5697b8b2021-03-24 09:17:02 +01004460 calculated_params["ns_config_info"] = instantiation_params[
4461 "ns_config_info"
4462 ]
tiernoda964822019-01-14 15:53:47 +00004463 return calculated_params
4464
garciadeblas5697b8b2021-03-24 09:17:02 +01004465 def _look_for_deployed_vca(
4466 self,
4467 deployed_vca,
4468 member_vnf_index,
4469 vdu_id,
4470 vdu_count_index,
4471 kdu_name=None,
4472 ee_descriptor_id=None,
4473 ):
tiernoe876f672020-02-13 14:34:48 +00004474 # find vca_deployed record for this action. Raise LcmException if not found or there is not any id.
4475 for vca in deployed_vca:
4476 if not vca:
4477 continue
4478 if member_vnf_index != vca["member-vnf-index"] or vdu_id != vca["vdu_id"]:
4479 continue
garciadeblas5697b8b2021-03-24 09:17:02 +01004480 if (
4481 vdu_count_index is not None
4482 and vdu_count_index != vca["vdu_count_index"]
4483 ):
tiernoe876f672020-02-13 14:34:48 +00004484 continue
4485 if kdu_name and kdu_name != vca["kdu_name"]:
4486 continue
tiernoa278b842020-07-08 15:33:55 +00004487 if ee_descriptor_id and ee_descriptor_id != vca["ee_descriptor_id"]:
4488 continue
tiernoe876f672020-02-13 14:34:48 +00004489 break
4490 else:
4491 # vca_deployed not found
garciadeblas5697b8b2021-03-24 09:17:02 +01004492 raise LcmException(
4493 "charm for member_vnf_index={} vdu_id={}.{} kdu_name={} execution-environment-list.id={}"
4494 " is not deployed".format(
4495 member_vnf_index,
4496 vdu_id,
4497 vdu_count_index,
4498 kdu_name,
4499 ee_descriptor_id,
4500 )
4501 )
tiernoe876f672020-02-13 14:34:48 +00004502 # get ee_id
4503 ee_id = vca.get("ee_id")
garciadeblas5697b8b2021-03-24 09:17:02 +01004504 vca_type = vca.get(
4505 "type", "lxc_proxy_charm"
4506 ) # default value for backward compatibility - proxy charm
tiernoe876f672020-02-13 14:34:48 +00004507 if not ee_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004508 raise LcmException(
4509 "charm for member_vnf_index={} vdu_id={} kdu_name={} vdu_count_index={} has not "
4510 "execution environment".format(
4511 member_vnf_index, vdu_id, kdu_name, vdu_count_index
4512 )
4513 )
tierno588547c2020-07-01 15:30:20 +00004514 return ee_id, vca_type
tiernoe876f672020-02-13 14:34:48 +00004515
David Garciac1fe90a2021-03-31 19:12:02 +02004516 async def _ns_execute_primitive(
4517 self,
4518 ee_id,
4519 primitive,
4520 primitive_params,
4521 retries=0,
4522 retries_interval=30,
4523 timeout=None,
4524 vca_type=None,
4525 db_dict=None,
4526 vca_id: str = None,
4527 ) -> (str, str):
tiernoda964822019-01-14 15:53:47 +00004528 try:
tierno98ad6ea2019-05-30 17:16:28 +00004529 if primitive == "config":
4530 primitive_params = {"params": primitive_params}
tierno2fc7ce52019-06-11 22:50:01 +00004531
tierno588547c2020-07-01 15:30:20 +00004532 vca_type = vca_type or "lxc_proxy_charm"
4533
quilesj7e13aeb2019-10-08 13:34:55 +02004534 while retries >= 0:
4535 try:
tierno067e04a2020-03-31 12:53:13 +00004536 output = await asyncio.wait_for(
tierno588547c2020-07-01 15:30:20 +00004537 self.vca_map[vca_type].exec_primitive(
tierno067e04a2020-03-31 12:53:13 +00004538 ee_id=ee_id,
4539 primitive_name=primitive,
4540 params_dict=primitive_params,
4541 progress_timeout=self.timeout_progress_primitive,
tierno588547c2020-07-01 15:30:20 +00004542 total_timeout=self.timeout_primitive,
David Garciac1fe90a2021-03-31 19:12:02 +02004543 db_dict=db_dict,
4544 vca_id=vca_id,
aktas730569b2021-07-29 17:42:49 +03004545 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004546 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004547 timeout=timeout or self.timeout_primitive,
4548 )
quilesj7e13aeb2019-10-08 13:34:55 +02004549 # execution was OK
4550 break
tierno067e04a2020-03-31 12:53:13 +00004551 except asyncio.CancelledError:
4552 raise
4553 except Exception as e: # asyncio.TimeoutError
4554 if isinstance(e, asyncio.TimeoutError):
4555 e = "Timeout"
quilesj7e13aeb2019-10-08 13:34:55 +02004556 retries -= 1
4557 if retries >= 0:
garciadeblas5697b8b2021-03-24 09:17:02 +01004558 self.logger.debug(
4559 "Error executing action {} on {} -> {}".format(
4560 primitive, ee_id, e
4561 )
4562 )
quilesj7e13aeb2019-10-08 13:34:55 +02004563 # wait and retry
4564 await asyncio.sleep(retries_interval, loop=self.loop)
tierno73d8bd02019-11-18 17:33:27 +00004565 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004566 return "FAILED", str(e)
quilesj7e13aeb2019-10-08 13:34:55 +02004567
garciadeblas5697b8b2021-03-24 09:17:02 +01004568 return "COMPLETED", output
quilesj7e13aeb2019-10-08 13:34:55 +02004569
tierno067e04a2020-03-31 12:53:13 +00004570 except (LcmException, asyncio.CancelledError):
tiernoe876f672020-02-13 14:34:48 +00004571 raise
quilesj7e13aeb2019-10-08 13:34:55 +02004572 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004573 return "FAIL", "Error executing action {}: {}".format(primitive, e)
tierno59d22d22018-09-25 18:10:19 +02004574
ksaikiranr3fde2c72021-03-15 10:39:06 +05304575 async def vca_status_refresh(self, nsr_id, nslcmop_id):
4576 """
4577 Updating the vca_status with latest juju information in nsrs record
4578 :param: nsr_id: Id of the nsr
4579 :param: nslcmop_id: Id of the nslcmop
4580 :return: None
4581 """
4582
4583 self.logger.debug("Task ns={} action={} Enter".format(nsr_id, nslcmop_id))
4584 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
David Garciac1fe90a2021-03-31 19:12:02 +02004585 vca_id = self.get_vca_id({}, db_nsr)
garciadeblas5697b8b2021-03-24 09:17:02 +01004586 if db_nsr["_admin"]["deployed"]["K8s"]:
4587 for k8s_index, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304588 cluster_uuid, kdu_instance = k8s["k8scluster-uuid"], k8s["kdu-instance"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004589 await self._on_update_k8s_db(
4590 cluster_uuid, kdu_instance, filter={"_id": nsr_id}, vca_id=vca_id
4591 )
ksaikiranr656b6dd2021-02-19 10:25:18 +05304592 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004593 for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]):
ksaikiranr656b6dd2021-02-19 10:25:18 +05304594 table, filter = "nsrs", {"_id": nsr_id}
4595 path = "_admin.deployed.VCA.{}.".format(vca_index)
4596 await self._on_update_n2vc_db(table, filter, path, {})
ksaikiranr3fde2c72021-03-15 10:39:06 +05304597
4598 self.logger.debug("Task ns={} action={} Exit".format(nsr_id, nslcmop_id))
4599 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_vca_status_refresh")
4600
tierno59d22d22018-09-25 18:10:19 +02004601 async def action(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004602 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004603 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004604 if not task_is_locked_by_me:
4605 return
4606
tierno59d22d22018-09-25 18:10:19 +02004607 logging_text = "Task ns={} action={} ".format(nsr_id, nslcmop_id)
4608 self.logger.debug(logging_text + "Enter")
4609 # get all needed from database
4610 db_nsr = None
4611 db_nslcmop = None
tiernoe876f672020-02-13 14:34:48 +00004612 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004613 db_nslcmop_update = {}
4614 nslcmop_operation_state = None
tierno067e04a2020-03-31 12:53:13 +00004615 error_description_nslcmop = None
tierno59d22d22018-09-25 18:10:19 +02004616 exc = None
4617 try:
kuused124bfe2019-06-18 12:09:24 +02004618 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004619 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004620 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004621
quilesj4cda56b2019-12-05 10:02:20 +00004622 self._write_ns_status(
4623 nsr_id=nsr_id,
4624 ns_state=None,
4625 current_operation="RUNNING ACTION",
garciadeblas5697b8b2021-03-24 09:17:02 +01004626 current_operation_id=nslcmop_id,
quilesj4cda56b2019-12-05 10:02:20 +00004627 )
4628
tierno59d22d22018-09-25 18:10:19 +02004629 step = "Getting information from database"
4630 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
4631 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
Guillermo Calvinofbf294c2022-01-26 17:40:31 +01004632 if db_nslcmop["operationParams"].get("primitive_params"):
4633 db_nslcmop["operationParams"]["primitive_params"] = json.loads(
4634 db_nslcmop["operationParams"]["primitive_params"]
4635 )
tiernoda964822019-01-14 15:53:47 +00004636
tiernoe4f7e6c2018-11-27 14:55:30 +00004637 nsr_deployed = db_nsr["_admin"].get("deployed")
tierno1b633412019-02-25 16:48:23 +00004638 vnf_index = db_nslcmop["operationParams"].get("member_vnf_index")
tierno59d22d22018-09-25 18:10:19 +02004639 vdu_id = db_nslcmop["operationParams"].get("vdu_id")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004640 kdu_name = db_nslcmop["operationParams"].get("kdu_name")
tiernoe4f7e6c2018-11-27 14:55:30 +00004641 vdu_count_index = db_nslcmop["operationParams"].get("vdu_count_index")
tierno067e04a2020-03-31 12:53:13 +00004642 primitive = db_nslcmop["operationParams"]["primitive"]
4643 primitive_params = db_nslcmop["operationParams"]["primitive_params"]
garciadeblas5697b8b2021-03-24 09:17:02 +01004644 timeout_ns_action = db_nslcmop["operationParams"].get(
4645 "timeout_ns_action", self.timeout_primitive
4646 )
tierno59d22d22018-09-25 18:10:19 +02004647
tierno1b633412019-02-25 16:48:23 +00004648 if vnf_index:
4649 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004650 db_vnfr = self.db.get_one(
4651 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
4652 )
tierno1b633412019-02-25 16:48:23 +00004653 step = "Getting vnfd from database"
4654 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
4655 else:
tierno067e04a2020-03-31 12:53:13 +00004656 step = "Getting nsd from database"
4657 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
tiernoda964822019-01-14 15:53:47 +00004658
David Garciac1fe90a2021-03-31 19:12:02 +02004659 vca_id = self.get_vca_id(db_vnfr, db_nsr)
tierno82974b22018-11-27 21:55:36 +00004660 # for backward compatibility
4661 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
4662 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
4663 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
4664 self.update_db_2("nsrs", nsr_id, db_nsr_update)
4665
tiernoda964822019-01-14 15:53:47 +00004666 # look for primitive
tiernoa278b842020-07-08 15:33:55 +00004667 config_primitive_desc = descriptor_configuration = None
tiernoda964822019-01-14 15:53:47 +00004668 if vdu_id:
bravofe5a31bc2021-02-17 19:09:12 -03004669 descriptor_configuration = get_configuration(db_vnfd, vdu_id)
calvinosanch9f9c6f22019-11-04 13:37:39 +01004670 elif kdu_name:
bravofe5a31bc2021-02-17 19:09:12 -03004671 descriptor_configuration = get_configuration(db_vnfd, kdu_name)
tierno1b633412019-02-25 16:48:23 +00004672 elif vnf_index:
bravofe5a31bc2021-02-17 19:09:12 -03004673 descriptor_configuration = get_configuration(db_vnfd, db_vnfd["id"])
tierno1b633412019-02-25 16:48:23 +00004674 else:
tiernoa278b842020-07-08 15:33:55 +00004675 descriptor_configuration = db_nsd.get("ns-configuration")
4676
garciadeblas5697b8b2021-03-24 09:17:02 +01004677 if descriptor_configuration and descriptor_configuration.get(
4678 "config-primitive"
4679 ):
tiernoa278b842020-07-08 15:33:55 +00004680 for config_primitive in descriptor_configuration["config-primitive"]:
tierno1b633412019-02-25 16:48:23 +00004681 if config_primitive["name"] == primitive:
4682 config_primitive_desc = config_primitive
4683 break
tiernoda964822019-01-14 15:53:47 +00004684
garciadeblas6bed6b32020-07-20 11:05:42 +00004685 if not config_primitive_desc:
4686 if not (kdu_name and primitive in ("upgrade", "rollback", "status")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004687 raise LcmException(
4688 "Primitive {} not found at [ns|vnf|vdu]-configuration:config-primitive ".format(
4689 primitive
4690 )
4691 )
garciadeblas6bed6b32020-07-20 11:05:42 +00004692 primitive_name = primitive
4693 ee_descriptor_id = None
4694 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004695 primitive_name = config_primitive_desc.get(
4696 "execution-environment-primitive", primitive
4697 )
4698 ee_descriptor_id = config_primitive_desc.get(
4699 "execution-environment-ref"
4700 )
tierno1b633412019-02-25 16:48:23 +00004701
tierno1b633412019-02-25 16:48:23 +00004702 if vnf_index:
tierno626e0152019-11-29 14:16:16 +00004703 if vdu_id:
garciadeblas5697b8b2021-03-24 09:17:02 +01004704 vdur = next(
4705 (x for x in db_vnfr["vdur"] if x["vdu-id-ref"] == vdu_id), None
4706 )
bravof922c4172020-11-24 21:21:43 -03004707 desc_params = parse_yaml_strings(vdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004708 elif kdu_name:
garciadeblas5697b8b2021-03-24 09:17:02 +01004709 kdur = next(
4710 (x for x in db_vnfr["kdur"] if x["kdu-name"] == kdu_name), None
4711 )
bravof922c4172020-11-24 21:21:43 -03004712 desc_params = parse_yaml_strings(kdur.get("additionalParams"))
tierno067e04a2020-03-31 12:53:13 +00004713 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004714 desc_params = parse_yaml_strings(
4715 db_vnfr.get("additionalParamsForVnf")
4716 )
tierno1b633412019-02-25 16:48:23 +00004717 else:
bravof922c4172020-11-24 21:21:43 -03004718 desc_params = parse_yaml_strings(db_nsr.get("additionalParamsForNs"))
bravofe5a31bc2021-02-17 19:09:12 -03004719 if kdu_name and get_configuration(db_vnfd, kdu_name):
4720 kdu_configuration = get_configuration(db_vnfd, kdu_name)
David Garciad41dbd62020-12-10 12:52:52 +01004721 actions = set()
David Garciaa1003662021-02-16 21:07:58 +01004722 for primitive in kdu_configuration.get("initial-config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004723 actions.add(primitive["name"])
David Garciaa1003662021-02-16 21:07:58 +01004724 for primitive in kdu_configuration.get("config-primitive", []):
David Garciad41dbd62020-12-10 12:52:52 +01004725 actions.add(primitive["name"])
4726 kdu_action = True if primitive_name in actions else False
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004727
tiernoda964822019-01-14 15:53:47 +00004728 # TODO check if ns is in a proper status
garciadeblas5697b8b2021-03-24 09:17:02 +01004729 if kdu_name and (
4730 primitive_name in ("upgrade", "rollback", "status") or kdu_action
4731 ):
tierno067e04a2020-03-31 12:53:13 +00004732 # kdur and desc_params already set from before
4733 if primitive_params:
4734 desc_params.update(primitive_params)
4735 # TODO Check if we will need something at vnf level
4736 for index, kdu in enumerate(get_iterable(nsr_deployed, "K8s")):
garciadeblas5697b8b2021-03-24 09:17:02 +01004737 if (
4738 kdu_name == kdu["kdu-name"]
4739 and kdu["member-vnf-index"] == vnf_index
4740 ):
tierno067e04a2020-03-31 12:53:13 +00004741 break
4742 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004743 raise LcmException(
4744 "KDU '{}' for vnf '{}' not deployed".format(kdu_name, vnf_index)
4745 )
quilesj7e13aeb2019-10-08 13:34:55 +02004746
tierno067e04a2020-03-31 12:53:13 +00004747 if kdu.get("k8scluster-type") not in self.k8scluster_map:
garciadeblas5697b8b2021-03-24 09:17:02 +01004748 msg = "unknown k8scluster-type '{}'".format(
4749 kdu.get("k8scluster-type")
4750 )
tierno067e04a2020-03-31 12:53:13 +00004751 raise LcmException(msg)
4752
garciadeblas5697b8b2021-03-24 09:17:02 +01004753 db_dict = {
4754 "collection": "nsrs",
4755 "filter": {"_id": nsr_id},
4756 "path": "_admin.deployed.K8s.{}".format(index),
4757 }
4758 self.logger.debug(
4759 logging_text
4760 + "Exec k8s {} on {}.{}".format(primitive_name, vnf_index, kdu_name)
4761 )
tiernoa278b842020-07-08 15:33:55 +00004762 step = "Executing kdu {}".format(primitive_name)
4763 if primitive_name == "upgrade":
tierno067e04a2020-03-31 12:53:13 +00004764 if desc_params.get("kdu_model"):
4765 kdu_model = desc_params.get("kdu_model")
4766 del desc_params["kdu_model"]
4767 else:
4768 kdu_model = kdu.get("kdu-model")
4769 parts = kdu_model.split(sep=":")
4770 if len(parts) == 2:
4771 kdu_model = parts[0]
4772
4773 detailed_status = await asyncio.wait_for(
4774 self.k8scluster_map[kdu["k8scluster-type"]].upgrade(
4775 cluster_uuid=kdu.get("k8scluster-uuid"),
4776 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004777 atomic=True,
4778 kdu_model=kdu_model,
4779 params=desc_params,
4780 db_dict=db_dict,
4781 timeout=timeout_ns_action,
4782 ),
4783 timeout=timeout_ns_action + 10,
4784 )
4785 self.logger.debug(
4786 logging_text + " Upgrade of kdu {} done".format(detailed_status)
4787 )
tiernoa278b842020-07-08 15:33:55 +00004788 elif primitive_name == "rollback":
tierno067e04a2020-03-31 12:53:13 +00004789 detailed_status = await asyncio.wait_for(
4790 self.k8scluster_map[kdu["k8scluster-type"]].rollback(
4791 cluster_uuid=kdu.get("k8scluster-uuid"),
4792 kdu_instance=kdu.get("kdu-instance"),
garciadeblas5697b8b2021-03-24 09:17:02 +01004793 db_dict=db_dict,
4794 ),
4795 timeout=timeout_ns_action,
4796 )
tiernoa278b842020-07-08 15:33:55 +00004797 elif primitive_name == "status":
tierno067e04a2020-03-31 12:53:13 +00004798 detailed_status = await asyncio.wait_for(
4799 self.k8scluster_map[kdu["k8scluster-type"]].status_kdu(
4800 cluster_uuid=kdu.get("k8scluster-uuid"),
David Garciac1fe90a2021-03-31 19:12:02 +02004801 kdu_instance=kdu.get("kdu-instance"),
4802 vca_id=vca_id,
4803 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004804 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004805 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004806 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004807 kdu_instance = kdu.get("kdu-instance") or "{}-{}".format(
4808 kdu["kdu-name"], nsr_id
4809 )
4810 params = self._map_primitive_params(
4811 config_primitive_desc, primitive_params, desc_params
4812 )
Dominik Fleischmann771c32b2020-04-07 12:39:36 +02004813
4814 detailed_status = await asyncio.wait_for(
4815 self.k8scluster_map[kdu["k8scluster-type"]].exec_primitive(
4816 cluster_uuid=kdu.get("k8scluster-uuid"),
4817 kdu_instance=kdu_instance,
tiernoa278b842020-07-08 15:33:55 +00004818 primitive_name=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004819 params=params,
4820 db_dict=db_dict,
David Garciac1fe90a2021-03-31 19:12:02 +02004821 timeout=timeout_ns_action,
4822 vca_id=vca_id,
4823 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01004824 timeout=timeout_ns_action,
David Garciac1fe90a2021-03-31 19:12:02 +02004825 )
tierno067e04a2020-03-31 12:53:13 +00004826
4827 if detailed_status:
garciadeblas5697b8b2021-03-24 09:17:02 +01004828 nslcmop_operation_state = "COMPLETED"
tierno067e04a2020-03-31 12:53:13 +00004829 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004830 detailed_status = ""
4831 nslcmop_operation_state = "FAILED"
tierno067e04a2020-03-31 12:53:13 +00004832 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01004833 ee_id, vca_type = self._look_for_deployed_vca(
4834 nsr_deployed["VCA"],
4835 member_vnf_index=vnf_index,
4836 vdu_id=vdu_id,
4837 vdu_count_index=vdu_count_index,
4838 ee_descriptor_id=ee_descriptor_id,
4839 )
4840 for vca_index, vca_deployed in enumerate(
4841 db_nsr["_admin"]["deployed"]["VCA"]
4842 ):
ksaikiranrb1c9f372021-03-15 11:07:29 +05304843 if vca_deployed.get("member-vnf-index") == vnf_index:
garciadeblas5697b8b2021-03-24 09:17:02 +01004844 db_dict = {
4845 "collection": "nsrs",
4846 "filter": {"_id": nsr_id},
4847 "path": "_admin.deployed.VCA.{}.".format(vca_index),
4848 }
ksaikiranrb1c9f372021-03-15 11:07:29 +05304849 break
garciadeblas5697b8b2021-03-24 09:17:02 +01004850 (
4851 nslcmop_operation_state,
4852 detailed_status,
4853 ) = await self._ns_execute_primitive(
tierno588547c2020-07-01 15:30:20 +00004854 ee_id,
tiernoa278b842020-07-08 15:33:55 +00004855 primitive=primitive_name,
garciadeblas5697b8b2021-03-24 09:17:02 +01004856 primitive_params=self._map_primitive_params(
4857 config_primitive_desc, primitive_params, desc_params
4858 ),
tierno588547c2020-07-01 15:30:20 +00004859 timeout=timeout_ns_action,
4860 vca_type=vca_type,
David Garciac1fe90a2021-03-31 19:12:02 +02004861 db_dict=db_dict,
4862 vca_id=vca_id,
4863 )
tierno067e04a2020-03-31 12:53:13 +00004864
4865 db_nslcmop_update["detailed-status"] = detailed_status
garciadeblas5697b8b2021-03-24 09:17:02 +01004866 error_description_nslcmop = (
4867 detailed_status if nslcmop_operation_state == "FAILED" else ""
4868 )
4869 self.logger.debug(
4870 logging_text
4871 + " task Done with result {} {}".format(
4872 nslcmop_operation_state, detailed_status
4873 )
4874 )
tierno59d22d22018-09-25 18:10:19 +02004875 return # database update is called inside finally
4876
tiernof59ad6c2020-04-08 12:50:52 +00004877 except (DbException, LcmException, N2VCException, K8sException) as e:
tierno59d22d22018-09-25 18:10:19 +02004878 self.logger.error(logging_text + "Exit Exception {}".format(e))
4879 exc = e
4880 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01004881 self.logger.error(
4882 logging_text + "Cancelled Exception while '{}'".format(step)
4883 )
tierno59d22d22018-09-25 18:10:19 +02004884 exc = "Operation was cancelled"
tierno067e04a2020-03-31 12:53:13 +00004885 except asyncio.TimeoutError:
4886 self.logger.error(logging_text + "Timeout while '{}'".format(step))
4887 exc = "Timeout"
tierno59d22d22018-09-25 18:10:19 +02004888 except Exception as e:
4889 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01004890 self.logger.critical(
4891 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
4892 exc_info=True,
4893 )
tierno59d22d22018-09-25 18:10:19 +02004894 finally:
tierno067e04a2020-03-31 12:53:13 +00004895 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01004896 db_nslcmop_update[
4897 "detailed-status"
4898 ] = (
4899 detailed_status
4900 ) = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tierno067e04a2020-03-31 12:53:13 +00004901 nslcmop_operation_state = "FAILED"
4902 if db_nsr:
4903 self._write_ns_status(
4904 nsr_id=nsr_id,
garciadeblas5697b8b2021-03-24 09:17:02 +01004905 ns_state=db_nsr[
4906 "nsState"
4907 ], # TODO check if degraded. For the moment use previous status
tierno067e04a2020-03-31 12:53:13 +00004908 current_operation="IDLE",
4909 current_operation_id=None,
4910 # error_description=error_description_nsr,
4911 # error_detail=error_detail,
garciadeblas5697b8b2021-03-24 09:17:02 +01004912 other_update=db_nsr_update,
tierno067e04a2020-03-31 12:53:13 +00004913 )
4914
garciadeblas5697b8b2021-03-24 09:17:02 +01004915 self._write_op_status(
4916 op_id=nslcmop_id,
4917 stage="",
4918 error_message=error_description_nslcmop,
4919 operation_state=nslcmop_operation_state,
4920 other_update=db_nslcmop_update,
4921 )
tierno067e04a2020-03-31 12:53:13 +00004922
tierno59d22d22018-09-25 18:10:19 +02004923 if nslcmop_operation_state:
4924 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01004925 await self.msg.aiowrite(
4926 "ns",
4927 "actioned",
4928 {
4929 "nsr_id": nsr_id,
4930 "nslcmop_id": nslcmop_id,
4931 "operationState": nslcmop_operation_state,
4932 },
4933 loop=self.loop,
4934 )
tierno59d22d22018-09-25 18:10:19 +02004935 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01004936 self.logger.error(
4937 logging_text + "kafka_write notification Exception {}".format(e)
4938 )
tierno59d22d22018-09-25 18:10:19 +02004939 self.logger.debug(logging_text + "Exit")
4940 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_action")
tierno067e04a2020-03-31 12:53:13 +00004941 return nslcmop_operation_state, detailed_status
tierno59d22d22018-09-25 18:10:19 +02004942
4943 async def scale(self, nsr_id, nslcmop_id):
kuused124bfe2019-06-18 12:09:24 +02004944 # Try to lock HA task here
garciadeblas5697b8b2021-03-24 09:17:02 +01004945 task_is_locked_by_me = self.lcm_tasks.lock_HA("ns", "nslcmops", nslcmop_id)
kuused124bfe2019-06-18 12:09:24 +02004946 if not task_is_locked_by_me:
4947 return
4948
tierno59d22d22018-09-25 18:10:19 +02004949 logging_text = "Task ns={} scale={} ".format(nsr_id, nslcmop_id)
garciadeblas5697b8b2021-03-24 09:17:02 +01004950 stage = ["", "", ""]
aktas13251562021-02-12 22:19:10 +03004951 tasks_dict_info = {}
tierno2357f4e2020-10-19 16:38:59 +00004952 # ^ stage, step, VIM progress
tierno59d22d22018-09-25 18:10:19 +02004953 self.logger.debug(logging_text + "Enter")
4954 # get all needed from database
4955 db_nsr = None
tierno59d22d22018-09-25 18:10:19 +02004956 db_nslcmop_update = {}
tiernoe876f672020-02-13 14:34:48 +00004957 db_nsr_update = {}
tierno59d22d22018-09-25 18:10:19 +02004958 exc = None
tierno9ab95942018-10-10 16:44:22 +02004959 # in case of error, indicates what part of scale was failed to put nsr at error status
4960 scale_process = None
tiernod6de1992018-10-11 13:05:52 +02004961 old_operational_status = ""
4962 old_config_status = ""
aktas13251562021-02-12 22:19:10 +03004963 nsi_id = None
tierno59d22d22018-09-25 18:10:19 +02004964 try:
kuused124bfe2019-06-18 12:09:24 +02004965 # wait for any previous tasks in process
tierno3cf81a32019-11-11 17:07:00 +00004966 step = "Waiting for previous operations to terminate"
garciadeblas5697b8b2021-03-24 09:17:02 +01004967 await self.lcm_tasks.waitfor_related_HA("ns", "nslcmops", nslcmop_id)
4968 self._write_ns_status(
4969 nsr_id=nsr_id,
4970 ns_state=None,
4971 current_operation="SCALING",
4972 current_operation_id=nslcmop_id,
4973 )
quilesj4cda56b2019-12-05 10:02:20 +00004974
ikalyvas02d9e7b2019-05-27 18:16:01 +03004975 step = "Getting nslcmop from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01004976 self.logger.debug(
4977 step + " after having waited for previous tasks to be completed"
4978 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03004979 db_nslcmop = self.db.get_one("nslcmops", {"_id": nslcmop_id})
bravof922c4172020-11-24 21:21:43 -03004980
ikalyvas02d9e7b2019-05-27 18:16:01 +03004981 step = "Getting nsr from database"
4982 db_nsr = self.db.get_one("nsrs", {"_id": nsr_id})
ikalyvas02d9e7b2019-05-27 18:16:01 +03004983 old_operational_status = db_nsr["operational-status"]
4984 old_config_status = db_nsr["config-status"]
bravof922c4172020-11-24 21:21:43 -03004985
tierno59d22d22018-09-25 18:10:19 +02004986 step = "Parsing scaling parameters"
4987 db_nsr_update["operational-status"] = "scaling"
4988 self.update_db_2("nsrs", nsr_id, db_nsr_update)
tiernoe4f7e6c2018-11-27 14:55:30 +00004989 nsr_deployed = db_nsr["_admin"].get("deployed")
calvinosanch9f9c6f22019-11-04 13:37:39 +01004990
garciadeblas5697b8b2021-03-24 09:17:02 +01004991 vnf_index = db_nslcmop["operationParams"]["scaleVnfData"][
4992 "scaleByStepData"
4993 ]["member-vnf-index"]
4994 scaling_group = db_nslcmop["operationParams"]["scaleVnfData"][
4995 "scaleByStepData"
4996 ]["scaling-group-descriptor"]
tierno59d22d22018-09-25 18:10:19 +02004997 scaling_type = db_nslcmop["operationParams"]["scaleVnfData"]["scaleVnfType"]
tierno82974b22018-11-27 21:55:36 +00004998 # for backward compatibility
4999 if nsr_deployed and isinstance(nsr_deployed.get("VCA"), dict):
5000 nsr_deployed["VCA"] = list(nsr_deployed["VCA"].values())
5001 db_nsr_update["_admin.deployed.VCA"] = nsr_deployed["VCA"]
5002 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5003
tierno59d22d22018-09-25 18:10:19 +02005004 step = "Getting vnfr from database"
garciadeblas5697b8b2021-03-24 09:17:02 +01005005 db_vnfr = self.db.get_one(
5006 "vnfrs", {"member-vnf-index-ref": vnf_index, "nsr-id-ref": nsr_id}
5007 )
bravof922c4172020-11-24 21:21:43 -03005008
David Garciac1fe90a2021-03-31 19:12:02 +02005009 vca_id = self.get_vca_id(db_vnfr, db_nsr)
5010
tierno59d22d22018-09-25 18:10:19 +02005011 step = "Getting vnfd from database"
5012 db_vnfd = self.db.get_one("vnfds", {"_id": db_vnfr["vnfd-id"]})
ikalyvas02d9e7b2019-05-27 18:16:01 +03005013
aktas13251562021-02-12 22:19:10 +03005014 base_folder = db_vnfd["_admin"]["storage"]
5015
tierno59d22d22018-09-25 18:10:19 +02005016 step = "Getting scaling-group-descriptor"
bravof832f8992020-12-07 12:57:31 -03005017 scaling_descriptor = find_in_list(
garciadeblas5697b8b2021-03-24 09:17:02 +01005018 get_scaling_aspect(db_vnfd),
5019 lambda scale_desc: scale_desc["name"] == scaling_group,
bravof832f8992020-12-07 12:57:31 -03005020 )
5021 if not scaling_descriptor:
garciadeblas5697b8b2021-03-24 09:17:02 +01005022 raise LcmException(
5023 "input parameter 'scaleByStepData':'scaling-group-descriptor':'{}' is not present "
5024 "at vnfd:scaling-group-descriptor".format(scaling_group)
5025 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005026
tierno15b1cf12019-08-29 13:21:40 +00005027 step = "Sending scale order to VIM"
bravof922c4172020-11-24 21:21:43 -03005028 # TODO check if ns is in a proper status
tierno59d22d22018-09-25 18:10:19 +02005029 nb_scale_op = 0
5030 if not db_nsr["_admin"].get("scaling-group"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005031 self.update_db_2(
5032 "nsrs",
5033 nsr_id,
5034 {
5035 "_admin.scaling-group": [
5036 {"name": scaling_group, "nb-scale-op": 0}
5037 ]
5038 },
5039 )
tierno59d22d22018-09-25 18:10:19 +02005040 admin_scale_index = 0
5041 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005042 for admin_scale_index, admin_scale_info in enumerate(
5043 db_nsr["_admin"]["scaling-group"]
5044 ):
tierno59d22d22018-09-25 18:10:19 +02005045 if admin_scale_info["name"] == scaling_group:
5046 nb_scale_op = admin_scale_info.get("nb-scale-op", 0)
5047 break
tierno9ab95942018-10-10 16:44:22 +02005048 else: # not found, set index one plus last element and add new entry with the name
5049 admin_scale_index += 1
garciadeblas5697b8b2021-03-24 09:17:02 +01005050 db_nsr_update[
5051 "_admin.scaling-group.{}.name".format(admin_scale_index)
5052 ] = scaling_group
aktas5f75f102021-03-15 11:26:10 +03005053
5054 vca_scaling_info = []
5055 scaling_info = {"scaling_group_name": scaling_group, "vdu": [], "kdu": []}
tierno59d22d22018-09-25 18:10:19 +02005056 if scaling_type == "SCALE_OUT":
bravof832f8992020-12-07 12:57:31 -03005057 if "aspect-delta-details" not in scaling_descriptor:
5058 raise LcmException(
5059 "Aspect delta details not fount in scaling descriptor {}".format(
5060 scaling_descriptor["name"]
5061 )
5062 )
tierno59d22d22018-09-25 18:10:19 +02005063 # count if max-instance-count is reached
bravof832f8992020-12-07 12:57:31 -03005064 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
kuuse8b998e42019-07-30 15:22:16 +02005065
aktas5f75f102021-03-15 11:26:10 +03005066 scaling_info["scaling_direction"] = "OUT"
5067 scaling_info["vdu-create"] = {}
5068 scaling_info["kdu-create"] = {}
bravof832f8992020-12-07 12:57:31 -03005069 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005070 for vdu_delta in delta.get("vdu-delta", {}):
bravof832f8992020-12-07 12:57:31 -03005071 vdud = get_vdu(db_vnfd, vdu_delta["id"])
aktas5f75f102021-03-15 11:26:10 +03005072 # vdu_index also provides the number of instance of the targeted vdu
5073 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
garciadeblas5697b8b2021-03-24 09:17:02 +01005074 cloud_init_text = self._get_vdu_cloud_init_content(
5075 vdud, db_vnfd
5076 )
tierno72ef84f2020-10-06 08:22:07 +00005077 if cloud_init_text:
garciadeblas5697b8b2021-03-24 09:17:02 +01005078 additional_params = (
5079 self._get_vdu_additional_params(db_vnfr, vdud["id"])
5080 or {}
5081 )
bravof832f8992020-12-07 12:57:31 -03005082 cloud_init_list = []
5083
5084 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5085 max_instance_count = 10
5086 if vdu_profile and "max-number-of-instances" in vdu_profile:
garciadeblas5697b8b2021-03-24 09:17:02 +01005087 max_instance_count = vdu_profile.get(
5088 "max-number-of-instances", 10
5089 )
5090
5091 default_instance_num = get_number_of_instances(
5092 db_vnfd, vdud["id"]
5093 )
aktas5f75f102021-03-15 11:26:10 +03005094 instances_number = vdu_delta.get("number-of-instances", 1)
5095 nb_scale_op += instances_number
bravof832f8992020-12-07 12:57:31 -03005096
aktas5f75f102021-03-15 11:26:10 +03005097 new_instance_count = nb_scale_op + default_instance_num
5098 # Control if new count is over max and vdu count is less than max.
5099 # Then assign new instance count
5100 if new_instance_count > max_instance_count > vdu_count:
5101 instances_number = new_instance_count - max_instance_count
5102 else:
5103 instances_number = instances_number
bravof832f8992020-12-07 12:57:31 -03005104
aktas5f75f102021-03-15 11:26:10 +03005105 if new_instance_count > max_instance_count:
bravof832f8992020-12-07 12:57:31 -03005106 raise LcmException(
5107 "reached the limit of {} (max-instance-count) "
5108 "scaling-out operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005109 "scaling-group-descriptor '{}'".format(
5110 nb_scale_op, scaling_group
5111 )
bravof922c4172020-11-24 21:21:43 -03005112 )
bravof832f8992020-12-07 12:57:31 -03005113 for x in range(vdu_delta.get("number-of-instances", 1)):
5114 if cloud_init_text:
5115 # TODO Information of its own ip is not available because db_vnfr is not updated.
5116 additional_params["OSM"] = get_osm_params(
garciadeblas5697b8b2021-03-24 09:17:02 +01005117 db_vnfr, vdu_delta["id"], vdu_index + x
bravof922c4172020-11-24 21:21:43 -03005118 )
bravof832f8992020-12-07 12:57:31 -03005119 cloud_init_list.append(
5120 self._parse_cloud_init(
5121 cloud_init_text,
5122 additional_params,
5123 db_vnfd["id"],
garciadeblas5697b8b2021-03-24 09:17:02 +01005124 vdud["id"],
bravof832f8992020-12-07 12:57:31 -03005125 )
5126 )
aktas5f75f102021-03-15 11:26:10 +03005127 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005128 {
5129 "osm_vdu_id": vdu_delta["id"],
5130 "member-vnf-index": vnf_index,
5131 "type": "create",
garciadeblas5697b8b2021-03-24 09:17:02 +01005132 "vdu_index": vdu_index + x,
aktas13251562021-02-12 22:19:10 +03005133 }
5134 )
aktas5f75f102021-03-15 11:26:10 +03005135 scaling_info["vdu-create"][vdu_delta["id"]] = instances_number
5136 for kdu_delta in delta.get("kdu-resource-delta", {}):
5137 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5138 kdu_name = kdu_profile["kdu-name"]
5139 resource_name = kdu_profile["resource-name"]
5140
5141 # Might have different kdus in the same delta
5142 # Should have list for each kdu
5143 if not scaling_info["kdu-create"].get(kdu_name, None):
5144 scaling_info["kdu-create"][kdu_name] = []
5145
5146 kdur = get_kdur(db_vnfr, kdu_name)
5147 if kdur.get("helm-chart"):
5148 k8s_cluster_type = "helm-chart-v3"
5149 self.logger.debug("kdur: {}".format(kdur))
5150 if (
5151 kdur.get("helm-version")
5152 and kdur.get("helm-version") == "v2"
5153 ):
5154 k8s_cluster_type = "helm-chart"
5155 raise NotImplementedError
5156 elif kdur.get("juju-bundle"):
5157 k8s_cluster_type = "juju-bundle"
5158 else:
5159 raise LcmException(
5160 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5161 "juju-bundle. Maybe an old NBI version is running".format(
5162 db_vnfr["member-vnf-index-ref"], kdu_name
5163 )
5164 )
5165
5166 max_instance_count = 10
5167 if kdu_profile and "max-number-of-instances" in kdu_profile:
5168 max_instance_count = kdu_profile.get(
5169 "max-number-of-instances", 10
5170 )
5171
5172 nb_scale_op += kdu_delta.get("number-of-instances", 1)
5173 deployed_kdu, _ = get_deployed_kdu(
5174 nsr_deployed, kdu_name, vnf_index
bravof832f8992020-12-07 12:57:31 -03005175 )
aktas5f75f102021-03-15 11:26:10 +03005176 if deployed_kdu is None:
5177 raise LcmException(
5178 "KDU '{}' for vnf '{}' not deployed".format(
5179 kdu_name, vnf_index
5180 )
5181 )
5182 kdu_instance = deployed_kdu.get("kdu-instance")
5183 instance_num = await self.k8scluster_map[
5184 k8s_cluster_type
5185 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5186 kdu_replica_count = instance_num + kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005187 "number-of-instances", 1
5188 )
ikalyvas02d9e7b2019-05-27 18:16:01 +03005189
aktas5f75f102021-03-15 11:26:10 +03005190 # Control if new count is over max and instance_num is less than max.
5191 # Then assign max instance number to kdu replica count
5192 if kdu_replica_count > max_instance_count > instance_num:
5193 kdu_replica_count = max_instance_count
5194 if kdu_replica_count > max_instance_count:
5195 raise LcmException(
5196 "reached the limit of {} (max-instance-count) "
5197 "scaling-out operations for the "
5198 "scaling-group-descriptor '{}'".format(
5199 instance_num, scaling_group
5200 )
5201 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005202
aktas5f75f102021-03-15 11:26:10 +03005203 for x in range(kdu_delta.get("number-of-instances", 1)):
5204 vca_scaling_info.append(
5205 {
5206 "osm_kdu_id": kdu_name,
5207 "member-vnf-index": vnf_index,
5208 "type": "create",
5209 "kdu_index": instance_num + x - 1,
5210 }
5211 )
5212 scaling_info["kdu-create"][kdu_name].append(
5213 {
5214 "member-vnf-index": vnf_index,
5215 "type": "create",
5216 "k8s-cluster-type": k8s_cluster_type,
5217 "resource-name": resource_name,
5218 "scale": kdu_replica_count,
5219 }
5220 )
5221 elif scaling_type == "SCALE_IN":
bravof832f8992020-12-07 12:57:31 -03005222 deltas = scaling_descriptor.get("aspect-delta-details")["deltas"]
aktas5f75f102021-03-15 11:26:10 +03005223
5224 scaling_info["scaling_direction"] = "IN"
5225 scaling_info["vdu-delete"] = {}
5226 scaling_info["kdu-delete"] = {}
5227
bravof832f8992020-12-07 12:57:31 -03005228 for delta in deltas:
aktas5f75f102021-03-15 11:26:10 +03005229 for vdu_delta in delta.get("vdu-delta", {}):
5230 vdu_count = vdu_index = get_vdur_index(db_vnfr, vdu_delta)
bravof832f8992020-12-07 12:57:31 -03005231 min_instance_count = 0
5232 vdu_profile = get_vdu_profile(db_vnfd, vdu_delta["id"])
5233 if vdu_profile and "min-number-of-instances" in vdu_profile:
5234 min_instance_count = vdu_profile["min-number-of-instances"]
5235
garciadeblas5697b8b2021-03-24 09:17:02 +01005236 default_instance_num = get_number_of_instances(
5237 db_vnfd, vdu_delta["id"]
5238 )
aktas5f75f102021-03-15 11:26:10 +03005239 instance_num = vdu_delta.get("number-of-instances", 1)
5240 nb_scale_op -= instance_num
bravof832f8992020-12-07 12:57:31 -03005241
aktas5f75f102021-03-15 11:26:10 +03005242 new_instance_count = nb_scale_op + default_instance_num
5243
5244 if new_instance_count < min_instance_count < vdu_count:
5245 instances_number = min_instance_count - new_instance_count
5246 else:
5247 instances_number = instance_num
5248
5249 if new_instance_count < min_instance_count:
bravof832f8992020-12-07 12:57:31 -03005250 raise LcmException(
5251 "reached the limit of {} (min-instance-count) scaling-in operations for the "
garciadeblas5697b8b2021-03-24 09:17:02 +01005252 "scaling-group-descriptor '{}'".format(
5253 nb_scale_op, scaling_group
5254 )
bravof832f8992020-12-07 12:57:31 -03005255 )
aktas13251562021-02-12 22:19:10 +03005256 for x in range(vdu_delta.get("number-of-instances", 1)):
aktas5f75f102021-03-15 11:26:10 +03005257 vca_scaling_info.append(
aktas13251562021-02-12 22:19:10 +03005258 {
5259 "osm_vdu_id": vdu_delta["id"],
5260 "member-vnf-index": vnf_index,
5261 "type": "delete",
garciadeblas5697b8b2021-03-24 09:17:02 +01005262 "vdu_index": vdu_index - 1 - x,
aktas13251562021-02-12 22:19:10 +03005263 }
5264 )
aktas5f75f102021-03-15 11:26:10 +03005265 scaling_info["vdu-delete"][vdu_delta["id"]] = instances_number
5266 for kdu_delta in delta.get("kdu-resource-delta", {}):
5267 kdu_profile = get_kdu_profile(db_vnfd, kdu_delta["id"])
5268 kdu_name = kdu_profile["kdu-name"]
5269 resource_name = kdu_profile["resource-name"]
5270
5271 if not scaling_info["kdu-delete"].get(kdu_name, None):
5272 scaling_info["kdu-delete"][kdu_name] = []
5273
5274 kdur = get_kdur(db_vnfr, kdu_name)
5275 if kdur.get("helm-chart"):
5276 k8s_cluster_type = "helm-chart-v3"
5277 self.logger.debug("kdur: {}".format(kdur))
5278 if (
5279 kdur.get("helm-version")
5280 and kdur.get("helm-version") == "v2"
5281 ):
5282 k8s_cluster_type = "helm-chart"
5283 raise NotImplementedError
5284 elif kdur.get("juju-bundle"):
5285 k8s_cluster_type = "juju-bundle"
5286 else:
5287 raise LcmException(
5288 "kdu type for kdu='{}.{}' is neither helm-chart nor "
5289 "juju-bundle. Maybe an old NBI version is running".format(
5290 db_vnfr["member-vnf-index-ref"], kdur["kdu-name"]
5291 )
5292 )
5293
5294 min_instance_count = 0
5295 if kdu_profile and "min-number-of-instances" in kdu_profile:
5296 min_instance_count = kdu_profile["min-number-of-instances"]
5297
5298 nb_scale_op -= kdu_delta.get("number-of-instances", 1)
5299 deployed_kdu, _ = get_deployed_kdu(
5300 nsr_deployed, kdu_name, vnf_index
5301 )
5302 if deployed_kdu is None:
5303 raise LcmException(
5304 "KDU '{}' for vnf '{}' not deployed".format(
5305 kdu_name, vnf_index
5306 )
5307 )
5308 kdu_instance = deployed_kdu.get("kdu-instance")
5309 instance_num = await self.k8scluster_map[
5310 k8s_cluster_type
5311 ].get_scale_count(resource_name, kdu_instance, vca_id=vca_id)
5312 kdu_replica_count = instance_num - kdu_delta.get(
garciadeblas5697b8b2021-03-24 09:17:02 +01005313 "number-of-instances", 1
5314 )
tierno59d22d22018-09-25 18:10:19 +02005315
aktas5f75f102021-03-15 11:26:10 +03005316 if kdu_replica_count < min_instance_count < instance_num:
5317 kdu_replica_count = min_instance_count
5318 if kdu_replica_count < min_instance_count:
5319 raise LcmException(
5320 "reached the limit of {} (min-instance-count) scaling-in operations for the "
5321 "scaling-group-descriptor '{}'".format(
5322 instance_num, scaling_group
5323 )
5324 )
5325
5326 for x in range(kdu_delta.get("number-of-instances", 1)):
5327 vca_scaling_info.append(
5328 {
5329 "osm_kdu_id": kdu_name,
5330 "member-vnf-index": vnf_index,
5331 "type": "delete",
5332 "kdu_index": instance_num - x - 1,
5333 }
5334 )
5335 scaling_info["kdu-delete"][kdu_name].append(
5336 {
5337 "member-vnf-index": vnf_index,
5338 "type": "delete",
5339 "k8s-cluster-type": k8s_cluster_type,
5340 "resource-name": resource_name,
5341 "scale": kdu_replica_count,
5342 }
5343 )
5344
tierno59d22d22018-09-25 18:10:19 +02005345 # update VDU_SCALING_INFO with the VDUs to delete ip_addresses
aktas5f75f102021-03-15 11:26:10 +03005346 vdu_delete = copy(scaling_info.get("vdu-delete"))
5347 if scaling_info["scaling_direction"] == "IN":
tierno59d22d22018-09-25 18:10:19 +02005348 for vdur in reversed(db_vnfr["vdur"]):
tierno27246d82018-09-27 15:59:09 +02005349 if vdu_delete.get(vdur["vdu-id-ref"]):
5350 vdu_delete[vdur["vdu-id-ref"]] -= 1
aktas5f75f102021-03-15 11:26:10 +03005351 scaling_info["vdu"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005352 {
5353 "name": vdur.get("name") or vdur.get("vdu-name"),
5354 "vdu_id": vdur["vdu-id-ref"],
5355 "interface": [],
5356 }
5357 )
tierno59d22d22018-09-25 18:10:19 +02005358 for interface in vdur["interfaces"]:
aktas5f75f102021-03-15 11:26:10 +03005359 scaling_info["vdu"][-1]["interface"].append(
garciadeblas5697b8b2021-03-24 09:17:02 +01005360 {
5361 "name": interface["name"],
5362 "ip_address": interface["ip-address"],
5363 "mac_address": interface.get("mac-address"),
5364 }
5365 )
tierno2357f4e2020-10-19 16:38:59 +00005366 # vdu_delete = vdu_scaling_info.pop("vdu-delete")
tierno59d22d22018-09-25 18:10:19 +02005367
kuuseac3a8882019-10-03 10:48:06 +02005368 # PRE-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005369 step = "Executing pre-scale vnf-config-primitive"
5370 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005371 for scaling_config_action in scaling_descriptor[
5372 "scaling-config-action"
5373 ]:
5374 if (
5375 scaling_config_action.get("trigger") == "pre-scale-in"
5376 and scaling_type == "SCALE_IN"
5377 ) or (
5378 scaling_config_action.get("trigger") == "pre-scale-out"
5379 and scaling_type == "SCALE_OUT"
5380 ):
5381 vnf_config_primitive = scaling_config_action[
5382 "vnf-config-primitive-name-ref"
5383 ]
5384 step = db_nslcmop_update[
5385 "detailed-status"
5386 ] = "executing pre-scale scaling-config-action '{}'".format(
5387 vnf_config_primitive
5388 )
tiernoda964822019-01-14 15:53:47 +00005389
tierno59d22d22018-09-25 18:10:19 +02005390 # look for primitive
garciadeblas5697b8b2021-03-24 09:17:02 +01005391 for config_primitive in (
5392 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5393 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005394 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005395 break
5396 else:
5397 raise LcmException(
5398 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-action"
tiernoda964822019-01-14 15:53:47 +00005399 "[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:config-"
garciadeblas5697b8b2021-03-24 09:17:02 +01005400 "primitive".format(scaling_group, vnf_config_primitive)
5401 )
tiernoda964822019-01-14 15:53:47 +00005402
aktas5f75f102021-03-15 11:26:10 +03005403 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005404 if db_vnfr.get("additionalParamsForVnf"):
5405 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
quilesj7e13aeb2019-10-08 13:34:55 +02005406
tierno9ab95942018-10-10 16:44:22 +02005407 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005408 db_nsr_update["config-status"] = "configuring pre-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005409 primitive_params = self._map_primitive_params(
5410 config_primitive, {}, vnfr_params
5411 )
kuuseac3a8882019-10-03 10:48:06 +02005412
tierno7c4e24c2020-05-13 08:41:35 +00005413 # Pre-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005414 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005415 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005416 vnf_index,
5417 vnf_config_primitive,
5418 primitive_params,
5419 "PRE-SCALE",
5420 )
tierno7c4e24c2020-05-13 08:41:35 +00005421 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005422 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005423 result = "COMPLETED"
5424 result_detail = "Done"
5425 self.logger.debug(
5426 logging_text
5427 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5428 vnf_config_primitive, result, result_detail
5429 )
5430 )
kuuseac3a8882019-10-03 10:48:06 +02005431 else:
tierno7c4e24c2020-05-13 08:41:35 +00005432 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005433 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005434 op_index = (
5435 len(db_nslcmop.get("_admin", {}).get("operations"))
5436 - 1
5437 )
5438 self.logger.debug(
5439 logging_text
5440 + "vnf_config_primitive={} New sub-operation".format(
5441 vnf_config_primitive
5442 )
5443 )
kuuseac3a8882019-10-03 10:48:06 +02005444 else:
tierno7c4e24c2020-05-13 08:41:35 +00005445 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005446 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5447 op_index
5448 ]
5449 vnf_index = op.get("member_vnf_index")
5450 vnf_config_primitive = op.get("primitive")
5451 primitive_params = op.get("primitive_params")
5452 self.logger.debug(
5453 logging_text
5454 + "vnf_config_primitive={} Sub-operation retry".format(
5455 vnf_config_primitive
5456 )
5457 )
tierno588547c2020-07-01 15:30:20 +00005458 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005459 ee_descriptor_id = config_primitive.get(
5460 "execution-environment-ref"
5461 )
5462 primitive_name = config_primitive.get(
5463 "execution-environment-primitive", vnf_config_primitive
5464 )
5465 ee_id, vca_type = self._look_for_deployed_vca(
5466 nsr_deployed["VCA"],
5467 member_vnf_index=vnf_index,
5468 vdu_id=None,
5469 vdu_count_index=None,
5470 ee_descriptor_id=ee_descriptor_id,
5471 )
kuuseac3a8882019-10-03 10:48:06 +02005472 result, result_detail = await self._ns_execute_primitive(
garciadeblas5697b8b2021-03-24 09:17:02 +01005473 ee_id,
5474 primitive_name,
David Garciac1fe90a2021-03-31 19:12:02 +02005475 primitive_params,
5476 vca_type=vca_type,
5477 vca_id=vca_id,
5478 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005479 self.logger.debug(
5480 logging_text
5481 + "vnf_config_primitive={} Done with result {} {}".format(
5482 vnf_config_primitive, result, result_detail
5483 )
5484 )
kuuseac3a8882019-10-03 10:48:06 +02005485 # Update operationState = COMPLETED | FAILED
5486 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005487 db_nslcmop, op_index, result, result_detail
5488 )
kuuseac3a8882019-10-03 10:48:06 +02005489
tierno59d22d22018-09-25 18:10:19 +02005490 if result == "FAILED":
5491 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005492 db_nsr_update["config-status"] = old_config_status
5493 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005494 # PRE-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005495
garciadeblas5697b8b2021-03-24 09:17:02 +01005496 db_nsr_update[
5497 "_admin.scaling-group.{}.nb-scale-op".format(admin_scale_index)
5498 ] = nb_scale_op
5499 db_nsr_update[
5500 "_admin.scaling-group.{}.time".format(admin_scale_index)
5501 ] = time()
tierno2357f4e2020-10-19 16:38:59 +00005502
aktas13251562021-02-12 22:19:10 +03005503 # SCALE-IN VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005504 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005505 step = db_nslcmop_update[
5506 "detailed-status"
5507 ] = "Deleting the execution environments"
aktas13251562021-02-12 22:19:10 +03005508 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005509 for vca_info in vca_scaling_info:
5510 if vca_info["type"] == "delete":
5511 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005512 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005513 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005514 )
aktas5f75f102021-03-15 11:26:10 +03005515 if vca_info.get("osm_vdu_id"):
5516 vdu_id = vca_info["osm_vdu_id"]
5517 vdu_index = int(vca_info["vdu_index"])
5518 stage[
5519 1
5520 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5521 member_vnf_index, vdu_id, vdu_index
5522 )
5523 else:
5524 vdu_index = 0
5525 kdu_id = vca_info["osm_kdu_id"]
5526 stage[
5527 1
5528 ] = "Scaling member_vnf_index={}, kdu_id={}, vdu_index={} ".format(
5529 member_vnf_index, kdu_id, vdu_index
5530 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005531 stage[2] = step = "Scaling in VCA"
5532 self._write_op_status(op_id=nslcmop_id, stage=stage)
aktas13251562021-02-12 22:19:10 +03005533 vca_update = db_nsr["_admin"]["deployed"]["VCA"]
5534 config_update = db_nsr["configurationStatus"]
5535 for vca_index, vca in enumerate(vca_update):
garciadeblas5697b8b2021-03-24 09:17:02 +01005536 if (
5537 (vca or vca.get("ee_id"))
5538 and vca["member-vnf-index"] == member_vnf_index
5539 and vca["vdu_count_index"] == vdu_index
5540 ):
aktas13251562021-02-12 22:19:10 +03005541 if vca.get("vdu_id"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005542 config_descriptor = get_configuration(
5543 db_vnfd, vca.get("vdu_id")
5544 )
aktas13251562021-02-12 22:19:10 +03005545 elif vca.get("kdu_name"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005546 config_descriptor = get_configuration(
5547 db_vnfd, vca.get("kdu_name")
5548 )
aktas13251562021-02-12 22:19:10 +03005549 else:
garciadeblas5697b8b2021-03-24 09:17:02 +01005550 config_descriptor = get_configuration(
5551 db_vnfd, db_vnfd["id"]
5552 )
5553 operation_params = (
5554 db_nslcmop.get("operationParams") or {}
5555 )
5556 exec_terminate_primitives = not operation_params.get(
5557 "skip_terminate_primitives"
5558 ) and vca.get("needed_terminate")
David Garciac1fe90a2021-03-31 19:12:02 +02005559 task = asyncio.ensure_future(
5560 asyncio.wait_for(
5561 self.destroy_N2VC(
5562 logging_text,
5563 db_nslcmop,
5564 vca,
5565 config_descriptor,
5566 vca_index,
5567 destroy_ee=True,
5568 exec_primitives=exec_terminate_primitives,
5569 scaling_in=True,
5570 vca_id=vca_id,
5571 ),
garciadeblas5697b8b2021-03-24 09:17:02 +01005572 timeout=self.timeout_charm_delete,
David Garciac1fe90a2021-03-31 19:12:02 +02005573 )
5574 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005575 tasks_dict_info[task] = "Terminating VCA {}".format(
5576 vca.get("ee_id")
5577 )
aktas13251562021-02-12 22:19:10 +03005578 del vca_update[vca_index]
5579 del config_update[vca_index]
5580 # wait for pending tasks of terminate primitives
5581 if tasks_dict_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005582 self.logger.debug(
5583 logging_text
5584 + "Waiting for tasks {}".format(
5585 list(tasks_dict_info.keys())
5586 )
5587 )
5588 error_list = await self._wait_for_tasks(
5589 logging_text,
5590 tasks_dict_info,
5591 min(
5592 self.timeout_charm_delete, self.timeout_ns_terminate
5593 ),
5594 stage,
5595 nslcmop_id,
5596 )
aktas13251562021-02-12 22:19:10 +03005597 tasks_dict_info.clear()
5598 if error_list:
5599 raise LcmException("; ".join(error_list))
5600
5601 db_vca_and_config_update = {
5602 "_admin.deployed.VCA": vca_update,
garciadeblas5697b8b2021-03-24 09:17:02 +01005603 "configurationStatus": config_update,
aktas13251562021-02-12 22:19:10 +03005604 }
garciadeblas5697b8b2021-03-24 09:17:02 +01005605 self.update_db_2(
5606 "nsrs", db_nsr["_id"], db_vca_and_config_update
5607 )
aktas13251562021-02-12 22:19:10 +03005608 scale_process = None
5609 # SCALE-IN VCA - END
5610
kuuseac3a8882019-10-03 10:48:06 +02005611 # SCALE RO - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005612 if scaling_info.get("vdu-create") or scaling_info.get("vdu-delete"):
tierno9ab95942018-10-10 16:44:22 +02005613 scale_process = "RO"
tierno2357f4e2020-10-19 16:38:59 +00005614 if self.ro_config.get("ng"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005615 await self._scale_ng_ro(
aktas5f75f102021-03-15 11:26:10 +03005616 logging_text, db_nsr, db_nslcmop, db_vnfr, scaling_info, stage
garciadeblas5697b8b2021-03-24 09:17:02 +01005617 )
aktas5f75f102021-03-15 11:26:10 +03005618 scaling_info.pop("vdu-create", None)
5619 scaling_info.pop("vdu-delete", None)
tierno59d22d22018-09-25 18:10:19 +02005620
tierno9ab95942018-10-10 16:44:22 +02005621 scale_process = None
aktas13251562021-02-12 22:19:10 +03005622 # SCALE RO - END
5623
aktas5f75f102021-03-15 11:26:10 +03005624 # SCALE KDU - BEGIN
5625 if scaling_info.get("kdu-create") or scaling_info.get("kdu-delete"):
5626 scale_process = "KDU"
5627 await self._scale_kdu(
5628 logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
5629 )
5630 scaling_info.pop("kdu-create", None)
5631 scaling_info.pop("kdu-delete", None)
5632
5633 scale_process = None
5634 # SCALE KDU - END
5635
5636 if db_nsr_update:
5637 self.update_db_2("nsrs", nsr_id, db_nsr_update)
5638
aktas13251562021-02-12 22:19:10 +03005639 # SCALE-UP VCA - BEGIN
aktas5f75f102021-03-15 11:26:10 +03005640 if vca_scaling_info:
garciadeblas5697b8b2021-03-24 09:17:02 +01005641 step = db_nslcmop_update[
5642 "detailed-status"
5643 ] = "Creating new execution environments"
aktas13251562021-02-12 22:19:10 +03005644 scale_process = "VCA"
aktas5f75f102021-03-15 11:26:10 +03005645 for vca_info in vca_scaling_info:
5646 if vca_info["type"] == "create":
5647 member_vnf_index = str(vca_info["member-vnf-index"])
garciadeblas5697b8b2021-03-24 09:17:02 +01005648 self.logger.debug(
aktas5f75f102021-03-15 11:26:10 +03005649 logging_text + "vdu info: {}".format(vca_info)
garciadeblas5697b8b2021-03-24 09:17:02 +01005650 )
aktas13251562021-02-12 22:19:10 +03005651 vnfd_id = db_vnfr["vnfd-ref"]
aktas5f75f102021-03-15 11:26:10 +03005652 if vca_info.get("osm_vdu_id"):
5653 vdu_index = int(vca_info["vdu_index"])
5654 deploy_params = {"OSM": get_osm_params(db_vnfr)}
5655 if db_vnfr.get("additionalParamsForVnf"):
5656 deploy_params.update(
5657 parse_yaml_strings(
5658 db_vnfr["additionalParamsForVnf"].copy()
5659 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005660 )
aktas5f75f102021-03-15 11:26:10 +03005661 descriptor_config = get_configuration(
5662 db_vnfd, db_vnfd["id"]
garciadeblas5697b8b2021-03-24 09:17:02 +01005663 )
aktas5f75f102021-03-15 11:26:10 +03005664 if descriptor_config:
5665 vdu_id = None
5666 vdu_name = None
5667 kdu_name = None
5668 self._deploy_n2vc(
5669 logging_text=logging_text
5670 + "member_vnf_index={} ".format(member_vnf_index),
5671 db_nsr=db_nsr,
5672 db_vnfr=db_vnfr,
5673 nslcmop_id=nslcmop_id,
5674 nsr_id=nsr_id,
5675 nsi_id=nsi_id,
5676 vnfd_id=vnfd_id,
5677 vdu_id=vdu_id,
5678 kdu_name=kdu_name,
5679 member_vnf_index=member_vnf_index,
5680 vdu_index=vdu_index,
5681 vdu_name=vdu_name,
5682 deploy_params=deploy_params,
5683 descriptor_config=descriptor_config,
5684 base_folder=base_folder,
5685 task_instantiation_info=tasks_dict_info,
5686 stage=stage,
5687 )
5688 vdu_id = vca_info["osm_vdu_id"]
5689 vdur = find_in_list(
5690 db_vnfr["vdur"], lambda vdu: vdu["vdu-id-ref"] == vdu_id
aktas13251562021-02-12 22:19:10 +03005691 )
aktas5f75f102021-03-15 11:26:10 +03005692 descriptor_config = get_configuration(db_vnfd, vdu_id)
5693 if vdur.get("additionalParams"):
5694 deploy_params_vdu = parse_yaml_strings(
5695 vdur["additionalParams"]
5696 )
5697 else:
5698 deploy_params_vdu = deploy_params
5699 deploy_params_vdu["OSM"] = get_osm_params(
5700 db_vnfr, vdu_id, vdu_count_index=vdu_index
garciadeblas5697b8b2021-03-24 09:17:02 +01005701 )
aktas5f75f102021-03-15 11:26:10 +03005702 if descriptor_config:
5703 vdu_name = None
5704 kdu_name = None
5705 stage[
5706 1
5707 ] = "Scaling member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
garciadeblas5697b8b2021-03-24 09:17:02 +01005708 member_vnf_index, vdu_id, vdu_index
aktas5f75f102021-03-15 11:26:10 +03005709 )
5710 stage[2] = step = "Scaling out VCA"
5711 self._write_op_status(op_id=nslcmop_id, stage=stage)
5712 self._deploy_n2vc(
5713 logging_text=logging_text
5714 + "member_vnf_index={}, vdu_id={}, vdu_index={} ".format(
5715 member_vnf_index, vdu_id, vdu_index
5716 ),
5717 db_nsr=db_nsr,
5718 db_vnfr=db_vnfr,
5719 nslcmop_id=nslcmop_id,
5720 nsr_id=nsr_id,
5721 nsi_id=nsi_id,
5722 vnfd_id=vnfd_id,
5723 vdu_id=vdu_id,
5724 kdu_name=kdu_name,
5725 member_vnf_index=member_vnf_index,
5726 vdu_index=vdu_index,
5727 vdu_name=vdu_name,
5728 deploy_params=deploy_params_vdu,
5729 descriptor_config=descriptor_config,
5730 base_folder=base_folder,
5731 task_instantiation_info=tasks_dict_info,
5732 stage=stage,
5733 )
5734 else:
5735 kdu_name = vca_info["osm_kdu_id"]
5736 descriptor_config = get_configuration(db_vnfd, kdu_name)
5737 if descriptor_config:
5738 vdu_id = None
5739 kdu_index = int(vca_info["kdu_index"])
5740 vdu_name = None
5741 kdur = next(
5742 x
5743 for x in db_vnfr["kdur"]
5744 if x["kdu-name"] == kdu_name
5745 )
5746 deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)}
5747 if kdur.get("additionalParams"):
5748 deploy_params_kdu = parse_yaml_strings(
5749 kdur["additionalParams"]
5750 )
5751
5752 self._deploy_n2vc(
5753 logging_text=logging_text,
5754 db_nsr=db_nsr,
5755 db_vnfr=db_vnfr,
5756 nslcmop_id=nslcmop_id,
5757 nsr_id=nsr_id,
5758 nsi_id=nsi_id,
5759 vnfd_id=vnfd_id,
5760 vdu_id=vdu_id,
5761 kdu_name=kdu_name,
5762 member_vnf_index=member_vnf_index,
5763 vdu_index=kdu_index,
5764 vdu_name=vdu_name,
5765 deploy_params=deploy_params_kdu,
5766 descriptor_config=descriptor_config,
5767 base_folder=base_folder,
5768 task_instantiation_info=tasks_dict_info,
5769 stage=stage,
5770 )
aktas13251562021-02-12 22:19:10 +03005771 # SCALE-UP VCA - END
5772 scale_process = None
tierno59d22d22018-09-25 18:10:19 +02005773
kuuseac3a8882019-10-03 10:48:06 +02005774 # POST-SCALE BEGIN
tierno59d22d22018-09-25 18:10:19 +02005775 # execute primitive service POST-SCALING
5776 step = "Executing post-scale vnf-config-primitive"
5777 if scaling_descriptor.get("scaling-config-action"):
garciadeblas5697b8b2021-03-24 09:17:02 +01005778 for scaling_config_action in scaling_descriptor[
5779 "scaling-config-action"
5780 ]:
5781 if (
5782 scaling_config_action.get("trigger") == "post-scale-in"
5783 and scaling_type == "SCALE_IN"
5784 ) or (
5785 scaling_config_action.get("trigger") == "post-scale-out"
5786 and scaling_type == "SCALE_OUT"
5787 ):
5788 vnf_config_primitive = scaling_config_action[
5789 "vnf-config-primitive-name-ref"
5790 ]
5791 step = db_nslcmop_update[
5792 "detailed-status"
5793 ] = "executing post-scale scaling-config-action '{}'".format(
5794 vnf_config_primitive
5795 )
tiernoda964822019-01-14 15:53:47 +00005796
aktas5f75f102021-03-15 11:26:10 +03005797 vnfr_params = {"VDU_SCALE_INFO": scaling_info}
tiernoda964822019-01-14 15:53:47 +00005798 if db_vnfr.get("additionalParamsForVnf"):
5799 vnfr_params.update(db_vnfr["additionalParamsForVnf"])
5800
tierno59d22d22018-09-25 18:10:19 +02005801 # look for primitive
bravof9a256db2021-02-22 18:02:07 -03005802 for config_primitive in (
5803 get_configuration(db_vnfd, db_vnfd["id"]) or {}
5804 ).get("config-primitive", ()):
tierno59d22d22018-09-25 18:10:19 +02005805 if config_primitive["name"] == vnf_config_primitive:
tierno59d22d22018-09-25 18:10:19 +02005806 break
5807 else:
tiernoa278b842020-07-08 15:33:55 +00005808 raise LcmException(
5809 "Invalid vnfd descriptor at scaling-group-descriptor[name='{}']:scaling-config-"
5810 "action[vnf-config-primitive-name-ref='{}'] does not match any vnf-configuration:"
garciadeblas5697b8b2021-03-24 09:17:02 +01005811 "config-primitive".format(
5812 scaling_group, vnf_config_primitive
5813 )
5814 )
tierno9ab95942018-10-10 16:44:22 +02005815 scale_process = "VCA"
tiernod6de1992018-10-11 13:05:52 +02005816 db_nsr_update["config-status"] = "configuring post-scaling"
garciadeblas5697b8b2021-03-24 09:17:02 +01005817 primitive_params = self._map_primitive_params(
5818 config_primitive, {}, vnfr_params
5819 )
tiernod6de1992018-10-11 13:05:52 +02005820
tierno7c4e24c2020-05-13 08:41:35 +00005821 # Post-scale retry check: Check if this sub-operation has been executed before
kuuseac3a8882019-10-03 10:48:06 +02005822 op_index = self._check_or_add_scale_suboperation(
garciadeblas5697b8b2021-03-24 09:17:02 +01005823 db_nslcmop,
garciadeblas5697b8b2021-03-24 09:17:02 +01005824 vnf_index,
5825 vnf_config_primitive,
5826 primitive_params,
5827 "POST-SCALE",
5828 )
quilesj4cda56b2019-12-05 10:02:20 +00005829 if op_index == self.SUBOPERATION_STATUS_SKIP:
kuuseac3a8882019-10-03 10:48:06 +02005830 # Skip sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005831 result = "COMPLETED"
5832 result_detail = "Done"
5833 self.logger.debug(
5834 logging_text
5835 + "vnf_config_primitive={} Skipped sub-operation, result {} {}".format(
5836 vnf_config_primitive, result, result_detail
5837 )
5838 )
kuuseac3a8882019-10-03 10:48:06 +02005839 else:
quilesj4cda56b2019-12-05 10:02:20 +00005840 if op_index == self.SUBOPERATION_STATUS_NEW:
kuuseac3a8882019-10-03 10:48:06 +02005841 # New sub-operation: Get index of this sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005842 op_index = (
5843 len(db_nslcmop.get("_admin", {}).get("operations"))
5844 - 1
5845 )
5846 self.logger.debug(
5847 logging_text
5848 + "vnf_config_primitive={} New sub-operation".format(
5849 vnf_config_primitive
5850 )
5851 )
kuuseac3a8882019-10-03 10:48:06 +02005852 else:
tierno7c4e24c2020-05-13 08:41:35 +00005853 # retry: Get registered params for this existing sub-operation
garciadeblas5697b8b2021-03-24 09:17:02 +01005854 op = db_nslcmop.get("_admin", {}).get("operations", [])[
5855 op_index
5856 ]
5857 vnf_index = op.get("member_vnf_index")
5858 vnf_config_primitive = op.get("primitive")
5859 primitive_params = op.get("primitive_params")
5860 self.logger.debug(
5861 logging_text
5862 + "vnf_config_primitive={} Sub-operation retry".format(
5863 vnf_config_primitive
5864 )
5865 )
tierno588547c2020-07-01 15:30:20 +00005866 # Execute the primitive, either with new (first-time) or registered (reintent) args
garciadeblas5697b8b2021-03-24 09:17:02 +01005867 ee_descriptor_id = config_primitive.get(
5868 "execution-environment-ref"
5869 )
5870 primitive_name = config_primitive.get(
5871 "execution-environment-primitive", vnf_config_primitive
5872 )
5873 ee_id, vca_type = self._look_for_deployed_vca(
5874 nsr_deployed["VCA"],
5875 member_vnf_index=vnf_index,
5876 vdu_id=None,
5877 vdu_count_index=None,
5878 ee_descriptor_id=ee_descriptor_id,
5879 )
kuuseac3a8882019-10-03 10:48:06 +02005880 result, result_detail = await self._ns_execute_primitive(
David Garciac1fe90a2021-03-31 19:12:02 +02005881 ee_id,
5882 primitive_name,
5883 primitive_params,
5884 vca_type=vca_type,
5885 vca_id=vca_id,
5886 )
garciadeblas5697b8b2021-03-24 09:17:02 +01005887 self.logger.debug(
5888 logging_text
5889 + "vnf_config_primitive={} Done with result {} {}".format(
5890 vnf_config_primitive, result, result_detail
5891 )
5892 )
kuuseac3a8882019-10-03 10:48:06 +02005893 # Update operationState = COMPLETED | FAILED
5894 self._update_suboperation_status(
garciadeblas5697b8b2021-03-24 09:17:02 +01005895 db_nslcmop, op_index, result, result_detail
5896 )
kuuseac3a8882019-10-03 10:48:06 +02005897
tierno59d22d22018-09-25 18:10:19 +02005898 if result == "FAILED":
5899 raise LcmException(result_detail)
tiernod6de1992018-10-11 13:05:52 +02005900 db_nsr_update["config-status"] = old_config_status
5901 scale_process = None
kuuseac3a8882019-10-03 10:48:06 +02005902 # POST-SCALE END
tierno59d22d22018-09-25 18:10:19 +02005903
garciadeblas5697b8b2021-03-24 09:17:02 +01005904 db_nsr_update[
5905 "detailed-status"
5906 ] = "" # "scaled {} {}".format(scaling_group, scaling_type)
5907 db_nsr_update["operational-status"] = (
5908 "running"
5909 if old_operational_status == "failed"
ikalyvas02d9e7b2019-05-27 18:16:01 +03005910 else old_operational_status
garciadeblas5697b8b2021-03-24 09:17:02 +01005911 )
tiernod6de1992018-10-11 13:05:52 +02005912 db_nsr_update["config-status"] = old_config_status
tierno59d22d22018-09-25 18:10:19 +02005913 return
garciadeblas5697b8b2021-03-24 09:17:02 +01005914 except (
5915 ROclient.ROClientException,
5916 DbException,
5917 LcmException,
5918 NgRoException,
5919 ) as e:
tierno59d22d22018-09-25 18:10:19 +02005920 self.logger.error(logging_text + "Exit Exception {}".format(e))
5921 exc = e
5922 except asyncio.CancelledError:
garciadeblas5697b8b2021-03-24 09:17:02 +01005923 self.logger.error(
5924 logging_text + "Cancelled Exception while '{}'".format(step)
5925 )
tierno59d22d22018-09-25 18:10:19 +02005926 exc = "Operation was cancelled"
5927 except Exception as e:
5928 exc = traceback.format_exc()
garciadeblas5697b8b2021-03-24 09:17:02 +01005929 self.logger.critical(
5930 logging_text + "Exit Exception {} {}".format(type(e).__name__, e),
5931 exc_info=True,
5932 )
tierno59d22d22018-09-25 18:10:19 +02005933 finally:
garciadeblas5697b8b2021-03-24 09:17:02 +01005934 self._write_ns_status(
5935 nsr_id=nsr_id,
5936 ns_state=None,
5937 current_operation="IDLE",
5938 current_operation_id=None,
5939 )
aktas13251562021-02-12 22:19:10 +03005940 if tasks_dict_info:
5941 stage[1] = "Waiting for instantiate pending tasks."
5942 self.logger.debug(logging_text + stage[1])
garciadeblas5697b8b2021-03-24 09:17:02 +01005943 exc = await self._wait_for_tasks(
5944 logging_text,
5945 tasks_dict_info,
5946 self.timeout_ns_deploy,
5947 stage,
5948 nslcmop_id,
5949 nsr_id=nsr_id,
5950 )
tierno59d22d22018-09-25 18:10:19 +02005951 if exc:
garciadeblas5697b8b2021-03-24 09:17:02 +01005952 db_nslcmop_update[
5953 "detailed-status"
5954 ] = error_description_nslcmop = "FAILED {}: {}".format(step, exc)
tiernoa17d4f42020-04-28 09:59:23 +00005955 nslcmop_operation_state = "FAILED"
tierno59d22d22018-09-25 18:10:19 +02005956 if db_nsr:
tiernod6de1992018-10-11 13:05:52 +02005957 db_nsr_update["operational-status"] = old_operational_status
5958 db_nsr_update["config-status"] = old_config_status
5959 db_nsr_update["detailed-status"] = ""
5960 if scale_process:
5961 if "VCA" in scale_process:
5962 db_nsr_update["config-status"] = "failed"
5963 if "RO" in scale_process:
5964 db_nsr_update["operational-status"] = "failed"
garciadeblas5697b8b2021-03-24 09:17:02 +01005965 db_nsr_update[
5966 "detailed-status"
5967 ] = "FAILED scaling nslcmop={} {}: {}".format(
5968 nslcmop_id, step, exc
5969 )
tiernoa17d4f42020-04-28 09:59:23 +00005970 else:
5971 error_description_nslcmop = None
5972 nslcmop_operation_state = "COMPLETED"
5973 db_nslcmop_update["detailed-status"] = "Done"
quilesj4cda56b2019-12-05 10:02:20 +00005974
garciadeblas5697b8b2021-03-24 09:17:02 +01005975 self._write_op_status(
5976 op_id=nslcmop_id,
5977 stage="",
5978 error_message=error_description_nslcmop,
5979 operation_state=nslcmop_operation_state,
5980 other_update=db_nslcmop_update,
5981 )
tiernoa17d4f42020-04-28 09:59:23 +00005982 if db_nsr:
garciadeblas5697b8b2021-03-24 09:17:02 +01005983 self._write_ns_status(
5984 nsr_id=nsr_id,
5985 ns_state=None,
5986 current_operation="IDLE",
5987 current_operation_id=None,
5988 other_update=db_nsr_update,
5989 )
tiernoa17d4f42020-04-28 09:59:23 +00005990
tierno59d22d22018-09-25 18:10:19 +02005991 if nslcmop_operation_state:
5992 try:
garciadeblas5697b8b2021-03-24 09:17:02 +01005993 msg = {
5994 "nsr_id": nsr_id,
5995 "nslcmop_id": nslcmop_id,
5996 "operationState": nslcmop_operation_state,
5997 }
bravof922c4172020-11-24 21:21:43 -03005998 await self.msg.aiowrite("ns", "scaled", msg, loop=self.loop)
tierno59d22d22018-09-25 18:10:19 +02005999 except Exception as e:
garciadeblas5697b8b2021-03-24 09:17:02 +01006000 self.logger.error(
6001 logging_text + "kafka_write notification Exception {}".format(e)
6002 )
tierno59d22d22018-09-25 18:10:19 +02006003 self.logger.debug(logging_text + "Exit")
6004 self.lcm_tasks.remove("ns", nsr_id, nslcmop_id, "ns_scale")
tiernob996d942020-07-03 14:52:28 +00006005
aktas5f75f102021-03-15 11:26:10 +03006006 async def _scale_kdu(
6007 self, logging_text, nsr_id, nsr_deployed, db_vnfd, vca_id, scaling_info
6008 ):
6009 _scaling_info = scaling_info.get("kdu-create") or scaling_info.get("kdu-delete")
6010 for kdu_name in _scaling_info:
6011 for kdu_scaling_info in _scaling_info[kdu_name]:
6012 deployed_kdu, index = get_deployed_kdu(
6013 nsr_deployed, kdu_name, kdu_scaling_info["member-vnf-index"]
6014 )
6015 cluster_uuid = deployed_kdu["k8scluster-uuid"]
6016 kdu_instance = deployed_kdu["kdu-instance"]
6017 scale = int(kdu_scaling_info["scale"])
6018 k8s_cluster_type = kdu_scaling_info["k8s-cluster-type"]
6019
6020 db_dict = {
6021 "collection": "nsrs",
6022 "filter": {"_id": nsr_id},
6023 "path": "_admin.deployed.K8s.{}".format(index),
6024 }
6025
6026 step = "scaling application {}".format(
6027 kdu_scaling_info["resource-name"]
6028 )
6029 self.logger.debug(logging_text + step)
6030
6031 if kdu_scaling_info["type"] == "delete":
6032 kdu_config = get_configuration(db_vnfd, kdu_name)
6033 if (
6034 kdu_config
6035 and kdu_config.get("terminate-config-primitive")
6036 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6037 ):
6038 terminate_config_primitive_list = kdu_config.get(
6039 "terminate-config-primitive"
6040 )
6041 terminate_config_primitive_list.sort(
6042 key=lambda val: int(val["seq"])
6043 )
6044
6045 for (
6046 terminate_config_primitive
6047 ) in terminate_config_primitive_list:
6048 primitive_params_ = self._map_primitive_params(
6049 terminate_config_primitive, {}, {}
6050 )
6051 step = "execute terminate config primitive"
6052 self.logger.debug(logging_text + step)
6053 await asyncio.wait_for(
6054 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6055 cluster_uuid=cluster_uuid,
6056 kdu_instance=kdu_instance,
6057 primitive_name=terminate_config_primitive["name"],
6058 params=primitive_params_,
6059 db_dict=db_dict,
6060 vca_id=vca_id,
6061 ),
6062 timeout=600,
6063 )
6064
6065 await asyncio.wait_for(
6066 self.k8scluster_map[k8s_cluster_type].scale(
6067 kdu_instance,
6068 scale,
6069 kdu_scaling_info["resource-name"],
6070 vca_id=vca_id,
6071 ),
6072 timeout=self.timeout_vca_on_error,
6073 )
6074
6075 if kdu_scaling_info["type"] == "create":
6076 kdu_config = get_configuration(db_vnfd, kdu_name)
6077 if (
6078 kdu_config
6079 and kdu_config.get("initial-config-primitive")
6080 and get_juju_ee_ref(db_vnfd, kdu_name) is None
6081 ):
6082 initial_config_primitive_list = kdu_config.get(
6083 "initial-config-primitive"
6084 )
6085 initial_config_primitive_list.sort(
6086 key=lambda val: int(val["seq"])
6087 )
6088
6089 for initial_config_primitive in initial_config_primitive_list:
6090 primitive_params_ = self._map_primitive_params(
6091 initial_config_primitive, {}, {}
6092 )
6093 step = "execute initial config primitive"
6094 self.logger.debug(logging_text + step)
6095 await asyncio.wait_for(
6096 self.k8scluster_map[k8s_cluster_type].exec_primitive(
6097 cluster_uuid=cluster_uuid,
6098 kdu_instance=kdu_instance,
6099 primitive_name=initial_config_primitive["name"],
6100 params=primitive_params_,
6101 db_dict=db_dict,
6102 vca_id=vca_id,
6103 ),
6104 timeout=600,
6105 )
6106
garciadeblas5697b8b2021-03-24 09:17:02 +01006107 async def _scale_ng_ro(
6108 self, logging_text, db_nsr, db_nslcmop, db_vnfr, vdu_scaling_info, stage
6109 ):
tierno2357f4e2020-10-19 16:38:59 +00006110 nsr_id = db_nslcmop["nsInstanceId"]
6111 db_nsd = self.db.get_one("nsds", {"_id": db_nsr["nsd-id"]})
6112 db_vnfrs = {}
6113
6114 # read from db: vnfd's for every vnf
bravof832f8992020-12-07 12:57:31 -03006115 db_vnfds = []
tierno2357f4e2020-10-19 16:38:59 +00006116
6117 # for each vnf in ns, read vnfd
6118 for vnfr in self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id}):
6119 db_vnfrs[vnfr["member-vnf-index-ref"]] = vnfr
6120 vnfd_id = vnfr["vnfd-id"] # vnfd uuid for this vnf
tierno2357f4e2020-10-19 16:38:59 +00006121 # if we haven't this vnfd, read it from db
bravof832f8992020-12-07 12:57:31 -03006122 if not find_in_list(db_vnfds, lambda a_vnfd: a_vnfd["id"] == vnfd_id):
tierno2357f4e2020-10-19 16:38:59 +00006123 # read from db
6124 vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
bravof832f8992020-12-07 12:57:31 -03006125 db_vnfds.append(vnfd)
tierno2357f4e2020-10-19 16:38:59 +00006126 n2vc_key = self.n2vc.get_public_key()
6127 n2vc_key_list = [n2vc_key]
garciadeblas5697b8b2021-03-24 09:17:02 +01006128 self.scale_vnfr(
6129 db_vnfr,
6130 vdu_scaling_info.get("vdu-create"),
6131 vdu_scaling_info.get("vdu-delete"),
6132 mark_delete=True,
6133 )
tierno2357f4e2020-10-19 16:38:59 +00006134 # db_vnfr has been updated, update db_vnfrs to use it
6135 db_vnfrs[db_vnfr["member-vnf-index-ref"]] = db_vnfr
garciadeblas5697b8b2021-03-24 09:17:02 +01006136 await self._instantiate_ng_ro(
6137 logging_text,
6138 nsr_id,
6139 db_nsd,
6140 db_nsr,
6141 db_nslcmop,
6142 db_vnfrs,
6143 db_vnfds,
6144 n2vc_key_list,
6145 stage=stage,
6146 start_deploy=time(),
6147 timeout_ns_deploy=self.timeout_ns_deploy,
6148 )
tierno2357f4e2020-10-19 16:38:59 +00006149 if vdu_scaling_info.get("vdu-delete"):
garciadeblas5697b8b2021-03-24 09:17:02 +01006150 self.scale_vnfr(
6151 db_vnfr, None, vdu_scaling_info["vdu-delete"], mark_delete=False
6152 )
tierno2357f4e2020-10-19 16:38:59 +00006153
garciadeblas5697b8b2021-03-24 09:17:02 +01006154 async def add_prometheus_metrics(
6155 self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip
6156 ):
tiernob996d942020-07-03 14:52:28 +00006157 if not self.prometheus:
6158 return
6159 # look if exist a file called 'prometheus*.j2' and
6160 artifact_content = self.fs.dir_ls(artifact_path)
garciadeblas5697b8b2021-03-24 09:17:02 +01006161 job_file = next(
6162 (
6163 f
6164 for f in artifact_content
6165 if f.startswith("prometheus") and f.endswith(".j2")
6166 ),
6167 None,
6168 )
tiernob996d942020-07-03 14:52:28 +00006169 if not job_file:
6170 return
6171 with self.fs.file_open((artifact_path, job_file), "r") as f:
6172 job_data = f.read()
6173
6174 # TODO get_service
garciadeblas5697b8b2021-03-24 09:17:02 +01006175 _, _, service = ee_id.partition(".") # remove prefix "namespace."
tiernob996d942020-07-03 14:52:28 +00006176 host_name = "{}-{}".format(service, ee_config_descriptor["metric-service"])
6177 host_port = "80"
6178 vnfr_id = vnfr_id.replace("-", "")
6179 variables = {
6180 "JOB_NAME": vnfr_id,
6181 "TARGET_IP": target_ip,
6182 "EXPORTER_POD_IP": host_name,
6183 "EXPORTER_POD_PORT": host_port,
6184 }
6185 job_list = self.prometheus.parse_job(job_data, variables)
6186 # ensure job_name is using the vnfr_id. Adding the metadata nsr_id
6187 for job in job_list:
garciadeblas5697b8b2021-03-24 09:17:02 +01006188 if (
6189 not isinstance(job.get("job_name"), str)
6190 or vnfr_id not in job["job_name"]
6191 ):
tiernob996d942020-07-03 14:52:28 +00006192 job["job_name"] = vnfr_id + "_" + str(randint(1, 10000))
6193 job["nsr_id"] = nsr_id
6194 job_dict = {jl["job_name"]: jl for jl in job_list}
6195 if await self.prometheus.update(job_dict):
6196 return list(job_dict.keys())
David Garciaaae391f2020-11-09 11:12:54 +01006197
6198 def get_vca_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6199 """
6200 Get VCA Cloud and VCA Cloud Credentials for the VIM account
6201
6202 :param: vim_account_id: VIM Account ID
6203
6204 :return: (cloud_name, cloud_credential)
6205 """
bravof922c4172020-11-24 21:21:43 -03006206 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006207 return config.get("vca_cloud"), config.get("vca_cloud_credential")
6208
6209 def get_vca_k8s_cloud_and_credentials(self, vim_account_id: str) -> (str, str):
6210 """
6211 Get VCA K8s Cloud and VCA K8s Cloud Credentials for the VIM account
6212
6213 :param: vim_account_id: VIM Account ID
6214
6215 :return: (cloud_name, cloud_credential)
6216 """
bravof922c4172020-11-24 21:21:43 -03006217 config = VimAccountDB.get_vim_account_with_id(vim_account_id).get("config", {})
David Garciaaae391f2020-11-09 11:12:54 +01006218 return config.get("vca_k8s_cloud"), config.get("vca_k8s_cloud_credential")