aboutsummaryrefslogtreecommitdiffstats
path: root/src/onapsdk/aai/business/vnf.py
blob: 2045291368723069c5298e2947241080ffa63d13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
"""Vnf instance module."""
#   Copyright 2022 Orange, Deutsche Telekom AG
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

from typing import Iterable, Iterator

from onapsdk.exceptions import ResourceNotFound, StatusError
from onapsdk.so.deletion import VnfDeletionRequest
from onapsdk.so.instantiation import VfModuleInstantiation, VnfInstantiation, SoService, \
    InstantiationParameter, VnfOperation
from onapsdk.configuration import settings

from .instance import Instance
from .vf_module import VfModuleInstance


class VnfInstance(Instance):  # pylint: disable=too-many-instance-attributes
    """VNF Instance class."""

    def __init__(self,  # pylint: disable=too-many-arguments, too-many-locals
                 service_instance: "ServiceInstance",
                 vnf_id: str,
                 vnf_type: str,
                 in_maint: bool,
                 is_closed_loop_disabled: bool,
                 vnf_name: str = None,
                 service_id: str = None,
                 regional_resource_zone: str = None,
                 prov_status: str = None,
                 operational_status: str = None,
                 equipment_role: str = None,
                 orchestration_status: str = None,
                 vnf_package_name: str = None,
                 vnf_discriptor_name: str = None,
                 job_id: str = None,
                 heat_stack_id: str = None,
                 mso_catalog_key: str = None,
                 management_option: str = None,
                 ipv4_oam_address: str = None,
                 ipv4_loopback0_address: str = None,
                 nm_lan_v6_address: str = None,
                 management_v6_address: str = None,
                 vcpu: int = None,
                 vcpu_units: str = None,
                 vmemory: int = None,
                 vmemory_units: str = None,
                 vdisk: int = None,
                 vdisk_units: str = None,
                 nshd: int = None,
                 nvm: int = None,
                 nnet: int = None,
                 resource_version: str = None,
                 encrypted_access_flag: bool = None,
                 model_invariant_id: str = None,
                 model_version_id: str = None,
                 persona_model_version: str = None,
                 model_customization_id: str = None,
                 widget_model_id: str = None,
                 widget_model_version: str = None,
                 as_number: str = None,
                 regional_resource_subzone: str = None,
                 nf_type: str = None,
                 nf_function: str = None,
                 nf_role: str = None,
                 nf_naming_code: str = None,
                 selflink: str = None,
                 ipv4_oam_gateway_address: str = None,
                 ipv4_oam_gateway_address_prefix_length: int = None,
                 vlan_id_outer: int = None,
                 nm_profile_name: str = None) -> None:
        """Vnf instance object initialization.

        Args:
            vnf_id (str): Unique id of VNF. This is unique across the graph.
            vnf_type (str): String capturing type of vnf, that was intended to identify
                the ASDC resource. This field has been overloaded in service-specific ways and
                clients should expect changes to occur in the future to this field as ECOMP
                matures.
            in_maint (bool): used to indicate whether or not this object is in maintenance mode
                (maintenance mode = true). This field (in conjunction with prov-status)
                is used to suppress alarms and vSCL on VNFs/VMs.
            is_closed_loop_disabled (bool): used to indicate whether closed loop function is
                enabled on this node
            vnf_name (str, optional): Name of VNF. Defaults to None.
            service_id (str, optional): Unique identifier of service, does not necessarily map to
                ASDC service models. Defaults to None.
            regional_resource_zone (str, optional): Regional way of organizing pservers, source of
                truth should define values. Defaults to None.
            prov_status (str, optional): Trigger for operational monitoring of this resource by
                Service Assurance systems. Defaults to None.
            operational_status (str, optional): Indicator for whether the resource is considered
                operational. Valid values are in-service-path and out-of-service-path.
                Defaults to None.
            equipment_role (str, optional): Client should send valid enumerated value.
                Defaults to None.
            orchestration_status (str, optional): Orchestration status of this VNF, used by MSO.
                Defaults to None.
            vnf_package_name (str, optional): vnf package name. Defaults to None.
            vnf_discriptor_name (str, optional): vnf discriptor name. Defaults to None.
            job_id (str, optional): job id corresponding to vnf. Defaults to None.
            heat_stack_id (str, optional): Heat stack id corresponding to this instance,
                managed by MSO. Defaults to None.
            mso_catalog_key (str, optional): Corresponds to the SDN-C catalog id used to
                configure this VCE. Defaults to None.
            management_option (str, optional): identifier of managed customer. Defaults to None.
            ipv4_oam_address (str, optional): Address tail-f uses to configure generic-vnf,
                also used for troubleshooting and is IP used for traps generated by generic-vnf.
                Defaults to None.
            ipv4_loopback0_address (str, optional): v4 Loopback0 address. Defaults to None.
            nm_lan_v6_address (str, optional): v6 Loopback address. Defaults to None.
            management_v6_address (str, optional): v6 management address. Defaults to None.
            vcpu (int, optional): number of vcpus ordered for this instance of VNF,
                used for VNFs with no vservers/flavors, to be used only by uCPE. Defaults to None.
            vcpu_units (str, optional): units associated with vcpu, used for VNFs with no
                vservers/flavors, to be used only by uCPE. Defaults to None.
            vmemory (int, optional): number of GB of memory ordered for this instance of VNF,
                used for VNFs with no vservers/flavors, to be used only by uCPE. Defaults to None.
            vmemory_units (str, optional): units associated with vmemory, used for VNFs with
                no vservers/flavors, to be used only by uCPE. Defaults to None.
            vdisk (int, optional): number of vdisks ordered for this instance of VNF,
                used for VNFs with no vservers/flavors, to be used only uCPE. Defaults to None.
            vdisk_units (str, optional): units associated with vdisk, used for VNFs with
                no vservers/flavors, to be used only by uCPE. Defaults to None.
            nshd (int, optional): number of associated SHD in vnf. Defaults to None.
            nvm (int, optional): number of vms in vnf. Defaults to None.
            nnet (int, optional): number of network in vnf. Defaults to None.
            resource_version (str, optional): Used for optimistic concurrency.
                Must be empty on create, valid on update and delete. Defaults to None.
            encrypted_access_flag (bool, optional): indicates whether generic-vnf access uses SSH.
                Defaults to None.
            model_invariant_id (str, optional): the ASDC model id for this resource or
                service model. Defaults to None.
            model_version_id (str, optional): the ASDC model version for this resource or
                service model. Defaults to None.
            persona_model_version (str, optional): the ASDC model version for this resource or
                service model. Defaults to None.
            model_customization_id (str, optional): captures the id of all the configuration used
                to customize the resource for the service. Defaults to None.
            widget_model_id (str, optional): the ASDC data dictionary widget model. This maps
                directly to the A&AI widget. Defaults to None.
            widget_model_version (str, optional): the ASDC data dictionary version of
                the widget model.This maps directly to the A&AI version of the widget.
                Defaults to None.
            as_number (str, optional): as-number of the VNF. Defaults to None.
            regional_resource_subzone (str, optional): represents sub zone of the rr plane.
                Defaults to None.
            nf_type (str, optional): Generic description of the type of NF. Defaults to None.
            nf_function (str, optional): English description of Network function that
                the specific VNF deployment is providing. Defaults to None.
            nf_role (str, optional): role in the network that this model will be providing.
                Defaults to None.
            nf_naming_code (str, optional): string assigned to this model used for naming purposes.
                Defaults to None.
            selflink (str, optional): Path to the controller object. Defaults to None.
            ipv4_oam_gateway_address (str, optional): Gateway address. Defaults to None.
            ipv4_oam_gateway_address_prefix_length (int, optional): Prefix length for oam-address.
                Defaults to None.
            vlan_id_outer (int, optional): Temporary location for S-TAG to get to VCE.
                Defaults to None.
            nm_profile_name (str, optional): Network Management profile of this VNF.
                Defaults to None.

        """
        super().__init__(resource_version=resource_version,
                         model_invariant_id=model_invariant_id,
                         model_version_id=model_version_id)
        self.service_instance: "ServiceInstance" = service_instance
        self.vnf_id: str = vnf_id
        self.vnf_type: str = vnf_type
        self.in_maint: bool = in_maint
        self.is_closed_loop_disabled: bool = is_closed_loop_disabled
        self.vnf_name: str = vnf_name
        self.service_id: str = service_id
        self.regional_resource_zone: str = regional_resource_zone
        self.prov_status: str = prov_status
        self.operational_status: str = operational_status
        self.equipment_role: str = equipment_role
        self.orchestration_status: str = orchestration_status
        self.vnf_package_name: str = vnf_package_name
        self.vnf_discriptor_name: str = vnf_discriptor_name
        self.job_id: str = job_id
        self.heat_stack_id: str = heat_stack_id
        self.mso_catalog_key: str = mso_catalog_key
        self.management_option: str = management_option
        self.ipv4_oam_address: str = ipv4_oam_address
        self.ipv4_loopback0_address: str = ipv4_loopback0_address
        self.nm_lan_v6_address: str = nm_lan_v6_address
        self.management_v6_address: str = management_v6_address
        self.vcpu: int = vcpu
        self.vcpu_units: str = vcpu_units
        self.vmemory: int = vmemory
        self.vmemory_units: str = vmemory_units
        self.vdisk: int = vdisk
        self.vdisk_units: str = vdisk_units
        self.nshd: int = nshd
        self.nvm: int = nvm
        self.nnet: int = nnet
        self.encrypted_access_flag: bool = encrypted_access_flag
        self.model_customization_id: str = model_customization_id
        self.as_number: str = as_number
        self.regional_resource_subzone: str = regional_resource_subzone
        self.nf_type: str = nf_type
        self.nf_function: str = nf_function
        self.nf_role: str = nf_role
        self.nf_naming_code: str = nf_naming_code
        self.selflink: str = selflink
        self.ipv4_oam_gateway_address: str = ipv4_oam_gateway_address
        self.ipv4_oam_gateway_address_prefix_length: int = ipv4_oam_gateway_address_prefix_length
        self.vlan_id_outer: int = vlan_id_outer
        self.nm_profile_name: str = nm_profile_name
        self.persona_model_version: str = persona_model_version
        self.widget_model_id: str = widget_model_id
        self.widget_model_version: str = widget_model_version

        self._vnf: "Vnf" = None

    def __repr__(self) -> str:
        """Vnf instance object representation.

        Returns:
            str: Human readable vnf instance representation

        """
        return (f"VnfInstance(vnf_id={self.vnf_id}, vnf_type={self.vnf_type}, "
                f"in_maint={self.in_maint}, "
                f"is_closed_loop_disabled={self.is_closed_loop_disabled})")

    @classmethod
    def get_all_url(cls) -> str:  # pylint: disable=arguments-differ
        """Return url to get all vnfs.

        Returns:
            str: Url to get all vnfs

        """
        return f"{cls.base_url}{cls.api_version}/network/generic-vnfs/"

    @property
    def url(self) -> str:
        """Vnf instance url.

        Returns:
            str: VnfInstance url

        """
        return f"{self.base_url}{self.api_version}/network/generic-vnfs/generic-vnf/{self.vnf_id}"

    @property
    def vf_modules(self) -> Iterator[VfModuleInstance]:
        """Vf modules associated with vnf instance.

        Yields:
            VfModuleInstance: VfModuleInstance associated with VnfInstance

        """
        for vf_module in self.send_message_json("GET",
                                                f"GET VNF {self.vnf_name} VF modules",
                                                f"{self.url}/vf-modules").get("vf-module", []):
            yield VfModuleInstance.create_from_api_response(vf_module, self)

    @property
    def vnf(self) -> "Vnf":
        """Vnf associated with that vnf instance.

        Raises:
            ResourceNotFound: Could not find VNF for that VNF instance

        Returns:
            Vnf: Vnf object associated with vnf instance

        """
        if not self._vnf:
            for vnf in self.service_instance.sdc_service.vnfs:
                if vnf.model_version_id == self.model_version_id:
                    self._vnf = vnf
                    return self._vnf

            msg = (
                f'Could not find VNF for the VNF instance'
                f' with model version ID "{self.model_version_id}"'
            )
            raise ResourceNotFound(msg)
        return self._vnf

    @classmethod
    def create_from_api_response(cls, api_response: dict,
                                 service_instance: "ServiceInstance") -> "VnfInstance":
        """Create vnf instance object using HTTP API response dictionary.

        Returns:
            VnfInstance: VnfInstance object

        """
        return cls(service_instance=service_instance,
                   vnf_id=api_response.get("vnf-id"),
                   vnf_type=api_response.get("vnf-type"),
                   in_maint=api_response.get("in-maint"),
                   is_closed_loop_disabled=api_response.get("is-closed-loop-disabled"),
                   vnf_name=api_response.get("vnf-name"),
                   service_id=api_response.get("service-id"),
                   regional_resource_zone=api_response.get("regional-resource-zone"),
                   prov_status=api_response.get("prov-status"),
                   operational_status=api_response.get("operational-status"),
                   equipment_role=api_response.get("equipment-role"),
                   orchestration_status=api_response.get("orchestration-status"),
                   vnf_package_name=api_response.get("vnf-package-name"),
                   vnf_discriptor_name=api_response.get("vnf-discriptor-name"),
                   job_id=api_response.get("job-id"),
                   heat_stack_id=api_response.get("heat-stack-id"),
                   mso_catalog_key=api_response.get("mso-catalog-key"),
                   management_option=api_response.get("management-option"),
                   ipv4_oam_address=api_response.get("ipv4-oam-address"),
                   ipv4_loopback0_address=api_response.get("ipv4-loopback0-address"),
                   nm_lan_v6_address=api_response.get("nm-lan-v6-address"),
                   management_v6_address=api_response.get("management-v6-address"),
                   vcpu=api_response.get("vcpu"),
                   vcpu_units=api_response.get("vcpu-units"),
                   vmemory=api_response.get("vmemory"),
                   vmemory_units=api_response.get("vmemory-units"),
                   vdisk=api_response.get("vdisk"),
                   vdisk_units=api_response.get("vdisk-units"),
                   nshd=api_response.get("nshd"),
                   nvm=api_response.get("nvm"),
                   nnet=api_response.get("nnet"),
                   resource_version=api_response.get("resource-version"),
                   model_invariant_id=api_response.get("model-invariant-id"),
                   model_version_id=api_response.get("model-version-id"),
                   encrypted_access_flag=api_response.get("encrypted-access-flag"),
                   persona_model_version=api_response.get("persona-model-version"),
                   model_customization_id=api_response.get("model-customization-id"),
                   widget_model_id=api_response.get("widget-model-id"),
                   widget_model_version=api_response.get("widget-model-version"),
                   as_number=api_response.get("as-number"),
                   regional_resource_subzone=api_response.get("regional-resource-subzone"),
                   nf_type=api_response.get("nf-type"),
                   nf_function=api_response.get("nf-function"),
                   nf_role=api_response.get("nf-role"),
                   nf_naming_code=api_response.get("nf-naming-code"),
                   selflink=api_response.get("selflink"),
                   ipv4_oam_gateway_address=api_response.get("ipv4-oam-gateway-address"),
                   ipv4_oam_gateway_address_prefix_length=\
                       api_response.get("ipv4-oam-gateway-address-prefix-length"),
                   vlan_id_outer=api_response.get("vlan-id-outer"),
                   nm_profile_name=api_response.get("nm-profile-name"))

    def add_vf_module(self,  # pylint: disable=too-many-arguments
                      vf_module: "VfModule",
                      cloud_region: "CloudRegion" = None,
                      tenant: "Tenant" = None,
                      vf_module_instance_name: str = None,
                      vnf_parameters: Iterable["InstantiationParameter"] = None,
                      use_preload: bool = True
                      ) -> "VfModuleInstantiation":
        """Instantiate vf module for that VNF instance.

        Args:
            vf_module (VfModule): VfModule to instantiate
            cloud_region (CloudRegion, optional): Cloud region to use in instantiation request.
                Defaults to None.
                THAT PROPERTY WILL BE REQUIRED IN ONE OF THE FUTURE RELEASE. REFACTOR YOUR CODE
                TO USE IT!.
            tenant (Tenant, optional): Tenant to use in instnatiation request.
                Defaults to None.
                THAT PROPERTY WILL BE REQUIRED IN ONE OF THE FUTURE RELEASE. REFACTOR YOUR CODE
                TO USE IT!.
            vf_module_instance_name (str, optional): VfModule instance name. Defaults to None.
            vnf_parameters (Iterable[InstantiationParameter], optional): InstantiationParameter
                to use for preloading or to be passed as "userParams". Defaults to None.
            use_preload (bool, optional): Based on this flag InstantiationParameters are passed
                in preload or as "userParam" in the request. Defaults to True

        Returns:
            VfModuleInstantiation: VfModuleInstantiation request object

        """
        return VfModuleInstantiation.instantiate_ala_carte(
            vf_module,
            self,
            cloud_region=cloud_region,
            tenant=tenant,
            vf_module_instance_name=vf_module_instance_name,
            vnf_parameters=vnf_parameters,
            use_preload=use_preload
        )

    def update(self,
               vnf_parameters: Iterable["InstantiationParameter"] = None
               ) -> VnfInstantiation:
        """Update vnf instance.

        Args:
            vnf_parameters (Iterable["InstantiationParameter"], Optional): list of instantiation
            parameters for update operation.
        Raises:
            StatusError: Skip post instantiation configuration  flag for VF to True.
                It might cause problems with SO component.

        Returns:
            VnfInstantiation: VnfInstantiation object.

        """
        skip_flag = next(p for p in self.vnf.properties
                         if p.name == 'skip_post_instantiation_configuration')
        if not skip_flag.value or skip_flag.value != "false":
            raise StatusError("Operation for the vnf is not supported! "
                              "Skip_post_instantiation_configuration flag for VF should be False")

        return self._execute_so_action(operation_type=VnfOperation.UPDATE,
                                       vnf_parameters=vnf_parameters)

    def healthcheck(self) -> VnfInstantiation:
        """Execute healthcheck operation for vnf instance.

        Returns:
            VnfInstantiation: VnfInstantiation object.

        """
        return self._execute_so_action(operation_type=VnfOperation.HEALTHCHECK)

    def _execute_so_action(self,
                           operation_type: VnfOperation,
                           vnf_parameters: Iterable["InstantiationParameter"] = None
                           ) -> VnfInstantiation:
        """Execute SO workflow for selected operation.

        Args:
            operation_type (str): Name of the operation to execute.
            vnf_parameters (Iterable["InstantiationParameter"], Optional): list of instantiation
            parameters for update operation.

        Returns:
            VnfInstantiation: VnfInstantiation object.

        """
        if not self.service_instance.active:
            msg = f'Service orchestration status must be "Active"'
            raise StatusError(msg)

        lob = settings.LOB
        platform = settings.PLATFORM

        for relationship in self.relationships:
            if relationship.related_to == "line-of-business":
                lob = relationship.relationship_data.pop().get("relationship-value")
            if relationship.related_to == "platform":
                platform = relationship.relationship_data.pop().get("relationship-value")

        so_input = self._build_so_input(vnf_params=vnf_parameters)

        return VnfInstantiation.so_action(
            vnf_instance=self,
            operation_type=operation_type,
            aai_service_instance=self.service_instance,
            line_of_business=lob,
            platform=platform,
            sdc_service=self.service_instance.sdc_service,
            so_service=so_input
        )

    def _build_so_input(self, vnf_params: Iterable[InstantiationParameter] = None) -> SoService:
        """Prepare so_input with params retrieved from existing service instance.

        Args:
            vnf_params (Iterable[InstantiationParameter], Optional): list of instantiation
            parameters for update operation.

        Returns:
            SoService: SoService object to store SO Service parameters used for macro instantiation.

        """
        so_vnfs = []
        so_pnfs = []

        if not vnf_params:
            vnf_params = []

        for pnf in self.service_instance.pnfs:
            _pnf = {
                "model_name": pnf.pnf.model_name,
                "instance_name": pnf.pnf_name
            }

            so_pnfs.append(_pnf)

        for vnf in self.service_instance.vnf_instances:
            _vnf = {"model_name": vnf.vnf.model_name,
                    "instance_name": vnf.vnf_name,
                    "parameters": {}}
            if vnf.vnf_name == self.vnf_name:
                for _param in vnf_params:
                    _vnf["parameters"][_param.name] = _param.value

            _vf_modules = []
            for vf_module in vnf.vf_modules:
                _vf_module = {
                    "model_name": vf_module.vf_module.model_name.split('..')[1],
                    "instance_name": vf_module.vf_module_name,
                    "parameters": {}
                }

                _vf_modules.append(_vf_module)

            _vnf["vf_modules"] = _vf_modules
            so_vnfs.append(_vnf)

        return SoService.load(data={
            'subscription_service_type': self.service_instance.service_subscription.service_type,
            'vnfs': so_vnfs,
            'pnfs': so_pnfs
        })

    def delete(self, a_la_carte: bool = True) -> "VnfDeletionRequest":
        """Create VNF deletion request.

        Send request to delete VNF instance

        Args:
            a_la_carte (boolean): deletion mode

        Returns:
            VnfDeletionRequest: Deletion request

        """
        self._logger.debug("Delete %s VNF", self.vnf_id)
        return VnfDeletionRequest.send_request(self, a_la_carte)