UserData script (VNF LCM v2)

This document describes the requirements of userdata script how to make it for VNF LCM version 2.

Userdata script enables operators to flexibly customize VIM input parameter in LCM operations.

If you would like to know how to deploy VNF using userdata script, please check ETSI NFV-SOL VNF Deployment as VM with LCM Operation User Data or like to know how to make VNF packages including userdata script, please check VNF Package manual.

Requirements

Userdata script must be described according to the following rules.

Userdata class needs to be defined in userdata script file. Any file name and class name are acceptable.

Note

The names of the file and class have to correspond to following request parameters of LCM API, “lcm-operation-user-data”, “lcm-operation-user-data-class”.

userdata class must inherit “userdata_utils.AbstractUserData”, then functions have to be implemented.

Followings are requirements for methods supported by latest Tacker.

Input of instantiate()

The function can use the following input data. The details of data types are defined in ETSI NFV SOL documents.

  • req: InstantiateVnfRequest

  • inst: VnfInstance

  • grant_req: GrantRequest

  • grant: Grants

  • tmp_csar_dir: the temporary path of csar expanded by Tacker.

Output of instantiate()

The function must return the following structure. Data are for stack create API in HEAT. The requirements of HEAT API are described in reference of Orchestration Service API v1 “POST /v1/{tenant_id}/stacks”

fields = {‘template’: value, ‘parameters’: value, ‘files’: value}

  • template: Dump of top HOT file.

  • parameters: Input parameters for Heat API.

  • files: Dump of all nested HOT files in the package.

Following shows sample output.

fields = {
            'template': yaml.safe_dump(top_hot),
            'parameters': {'nfv': nfv_dict},
            'files': {}
        }
        for key, value in hot_dict.get('files', {}).items():
            fields['files'][key] = yaml.safe_dump(value)

        return fields

Input of scale()

The function can use the following input data. The details of data types are defined in ETSI NFV SOL documents.

  • req: InstantiateVnfRequest

  • inst: VnfInstance

  • grant_req: GrantRequest

  • grant: Grants

  • tmp_csar_dir: the temporary path of csar expanded by Tacker.

Output of scale()

The function must return the following structure. Data are for update stack API in HEAT. The requirements of HEAT API are described in reference of Orchestration Service API v1 “PATCH /v1/{tenant_id}/stacks/{stack_name}/{stack_id}”

fields = {‘parameters’: {‘nfv’: {‘VDU’: new_vdus}}}

  • parameters: Input parameters for Heat API.

Following shows sample output.

fields = {'parameters': {'nfv': {'VDU': new_vdus}}}

return fields

Input of scale_rollback()

The function can use the following input data. The details of data types are defined in ETSI NFV SOL documents.

  • req: InstantiateVnfRequest

  • inst: VnfInstance

  • grant_req: GrantRequest

  • grant: Grants

  • tmp_csar_dir: the temporary path of csar expanded by Tacker.

Output of scale_rollback()

The function must return the following structure. Data are for update stack API in HEAT. The requirements of HEAT API are described in reference of Orchestration Service API v1 “PATCH /v1/{tenant_id}/stacks/{stack_name}/{stack_id}”

fields = {‘parameters’: {‘nfv’: {‘VDU’: new_vdus}}}

  • parameters: Input parameters for Heat API.

Following shows sample output.

fields = {'parameters': {'nfv': {'VDU': new_vdus}}}

return fields

Input of change_ext_conn_rollback()

The function can use the following input data. The details of data types are defined in ETSI NFV SOL documents.

  • req: InstantiateVnfRequest

  • inst: VnfInstance

  • grant_req: GrantRequest

  • grant: Grants

  • tmp_csar_dir: the temporary path of csar expanded by Tacker.

Output of change_ext_conn_rollback()

The function must return the following structure. Data are for update stack API in HEAT. The requirements of HEAT API are described in reference of Orchestration Service API v1 “PATCH /v1/{tenant_id}/stacks/{stack_name}/{stack_id}”

fields = {‘parameters’: {‘nfv’: {‘CP’: new_cps}}}

  • parameters: Input parameters for Heat API.

Following shows sample output.

fields = {'parameters': {'nfv': {'CP': new_cps}}}

return fields

Input of change_ext_conn()

The function can use the following input data. The details of data types are defined in ETSI NFV SOL documents.

  • req: InstantiateVnfRequest

  • inst: VnfInstance

  • grant_req: GrantRequest

  • grant: Grants

  • tmp_csar_dir: the temporary path of csar expanded by Tacker.

Output of change_ext_conn()

The function must return the following structure. Data are for update stack API in HEAT. The requirements of HEAT API are described in reference of Orchestration Service API v1 “PATCH /v1/{tenant_id}/stacks/{stack_name}/{stack_id}”

fields = {‘parameters’: {‘nfv’: {‘CP’: new_cps}}}

  • parameters: Input parameters for Heat API.

Following shows sample output.

fields = {'parameters': {'nfv': {'CP': new_cps}}}

return fields

Input of heal()

The function can use the following input data. The details of data types are defined in ETSI NFV SOL documents.

  • req: InstantiateVnfRequest

  • inst: VnfInstance

  • grant_req: GrantRequest

  • grant: Grants

  • tmp_csar_dir: the temporary path of csar expanded by Tacker.

Output of heal()

The function must return the following structure. Data are for update stack API in HEAT. The requirements of HEAT API are described in reference of Orchestration Service API v1 “PATCH /v1/{tenant_id}/stacks/{stack_name}/{stack_id}”

fields = {‘parameters’: {‘nfv’: {}}}

  • parameters: Input parameters for Heat API.

Following shows sample output.

fields = {'parameters': {'nfv': {}}}

return fields

Sample userdata script

If users do not specify the userdata in instantiate VNF request, the default process runs according to the following script.

The script can be used as a sample for making the original userdata script. It obtains HEAT input parameters such as computeFlavourId, vcImageId, locationConstraints, network, subnet, and fixed_ips from VNFD, parameters of Instantiate request and Grant.

# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
# All Rights Reserved.
#
#    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.

import yaml

from tacker.sol_refactored.common import common_script_utils
from tacker.sol_refactored.common import vnf_instance_utils as inst_utils
from tacker.sol_refactored.infra_drivers.openstack import userdata_utils


class DefaultUserData(userdata_utils.AbstractUserData):

    @staticmethod
    def instantiate(req, inst, grant_req, grant, tmp_csar_dir):
        vnfd = common_script_utils.get_vnfd(inst['vnfdId'], tmp_csar_dir)
        flavour_id = req['flavourId']

        hot_dict = vnfd.get_base_hot(flavour_id)
        top_hot = hot_dict['template']

        nfv_dict = common_script_utils.init_nfv_dict(top_hot)

        vdus = nfv_dict.get('VDU', {})
        for vdu_name, vdu_value in vdus.items():
            if 'computeFlavourId' in vdu_value:
                vdu_value['computeFlavourId'] = (
                    common_script_utils.get_param_flavor(
                        vdu_name, flavour_id, vnfd, grant))
            if 'vcImageId' in vdu_value:
                vdu_value['vcImageId'] = common_script_utils.get_param_image(
                    vdu_name, flavour_id, vnfd, grant)
            if 'locationConstraints' in vdu_value:
                vdu_value['locationConstraints'] = (
                    common_script_utils.get_param_zone(
                        vdu_name, grant_req, grant))
            if 'desired_capacity' in vdu_value:
                vdu_value['desired_capacity'] = (
                    common_script_utils.get_param_capacity(
                        vdu_name, inst, grant_req))

        cps = nfv_dict.get('CP', {})
        for cp_name, cp_value in cps.items():
            if 'network' in cp_value:
                cp_value['network'] = common_script_utils.get_param_network(
                    cp_name, grant, req)
            if 'fixed_ips' in cp_value:
                ext_fixed_ips = common_script_utils.get_param_fixed_ips(
                    cp_name, grant, req)
                fixed_ips = []
                for i in range(len(ext_fixed_ips)):
                    if i not in cp_value['fixed_ips']:
                        break
                    ips_i = cp_value['fixed_ips'][i]
                    if 'subnet' in ips_i:
                        ips_i['subnet'] = ext_fixed_ips[i].get('subnet')
                    if 'ip_address' in ips_i:
                        ips_i['ip_address'] = ext_fixed_ips[i].get(
                            'ip_address')
                    fixed_ips.append(ips_i)
                cp_value['fixed_ips'] = fixed_ips

        common_script_utils.apply_ext_managed_vls(top_hot, req, grant)

        if 'nfv' in req.get('additionalParams', {}):
            nfv_dict = inst_utils.json_merge_patch(nfv_dict,
                    req['additionalParams']['nfv'])
        if 'nfv' in grant.get('additionalParams', {}):
            nfv_dict = inst_utils.json_merge_patch(nfv_dict,
                    grant['additionalParams']['nfv'])

        fields = {
            'template': yaml.safe_dump(top_hot),
            'parameters': {'nfv': nfv_dict},
            'files': {}
        }
        for key, value in hot_dict.get('files', {}).items():
            fields['files'][key] = yaml.safe_dump(value)

        return fields

    @staticmethod
    def scale(req, inst, grant_req, grant, tmp_csar_dir):
        # scale is interested in 'desired_capacity' only.
        # This method returns only 'desired_capacity' part in the
        # 'nfv' dict. It is applied to json merge patch against
        # the existing 'nfv' dict by the caller.
        # NOTE: complete 'nfv' dict can not be made at the moment
        # since InstantiateVnfRequest is necessary to make it.

        vnfd = common_script_utils.get_vnfd(inst['vnfdId'], tmp_csar_dir)
        flavour_id = inst['instantiatedVnfInfo']['flavourId']

        hot_dict = vnfd.get_base_hot(flavour_id)
        top_hot = hot_dict['template']

        nfv_dict = common_script_utils.init_nfv_dict(top_hot)

        vdus = nfv_dict.get('VDU', {})
        new_vdus = {}
        for vdu_name, vdu_value in vdus.items():
            if 'desired_capacity' in vdu_value:
                capacity = common_script_utils.get_param_capacity(
                    vdu_name, inst, grant_req)
                new_vdus[vdu_name] = {'desired_capacity': capacity}

        fields = {'parameters': {'nfv': {'VDU': new_vdus}}}

        return fields

    @staticmethod
    def scale_rollback(req, inst, grant_req, grant, tmp_csar_dir):
        # NOTE: This method is not called by a userdata script but
        # is called by the openstack infra_driver directly now.
        # It is thought that it is suitable that this method defines
        # here since it is very likely to scale method above.

        vnfd = common_script_utils.get_vnfd(inst['vnfdId'], tmp_csar_dir)
        flavour_id = inst['instantiatedVnfInfo']['flavourId']

        hot_dict = vnfd.get_base_hot(flavour_id)
        top_hot = hot_dict['template']

        nfv_dict = common_script_utils.init_nfv_dict(top_hot)

        vdus = nfv_dict.get('VDU', {})
        new_vdus = {}
        for vdu_name, vdu_value in vdus.items():
            if 'desired_capacity' in vdu_value:
                capacity = common_script_utils.get_current_capacity(
                    vdu_name, inst)
                new_vdus[vdu_name] = {'desired_capacity': capacity}

        fields = {'parameters': {'nfv': {'VDU': new_vdus}}}

        return fields

    @staticmethod
    def change_ext_conn(req, inst, grant_req, grant, tmp_csar_dir):
        # change_ext_conn is interested in 'CP' only.
        # This method returns only 'CP' part in the 'nfv' dict from
        # ChangeExtVnfConnectivityRequest.
        # It is applied to json merge patch against the existing 'nfv'
        # dict by the caller.
        # NOTE: complete 'nfv' dict can not be made at the moment
        # since InstantiateVnfRequest is necessary to make it.

        vnfd = common_script_utils.get_vnfd(inst['vnfdId'], tmp_csar_dir)
        flavour_id = inst['instantiatedVnfInfo']['flavourId']

        hot_dict = vnfd.get_base_hot(flavour_id)
        top_hot = hot_dict['template']

        nfv_dict = common_script_utils.init_nfv_dict(top_hot)

        cps = nfv_dict.get('CP', {})
        new_cps = {}
        for cp_name, cp_value in cps.items():
            if 'network' in cp_value:
                network = common_script_utils.get_param_network(
                    cp_name, grant, req)
                if network is None:
                    continue
                new_cps.setdefault(cp_name, {})
                new_cps[cp_name]['network'] = network
            if 'fixed_ips' in cp_value:
                ext_fixed_ips = common_script_utils.get_param_fixed_ips(
                    cp_name, grant, req)
                fixed_ips = []
                for i in range(len(ext_fixed_ips)):
                    if i not in cp_value['fixed_ips']:
                        break
                    ips_i = cp_value['fixed_ips'][i]
                    if 'subnet' in ips_i:
                        ips_i['subnet'] = ext_fixed_ips[i].get('subnet')
                    if 'ip_address' in ips_i:
                        ips_i['ip_address'] = ext_fixed_ips[i].get(
                            'ip_address')
                    fixed_ips.append(ips_i)
                new_cps.setdefault(cp_name, {})
                new_cps[cp_name]['fixed_ips'] = fixed_ips

        fields = {'parameters': {'nfv': {'CP': new_cps}}}

        return fields

    @staticmethod
    def change_ext_conn_rollback(req, inst, grant_req, grant, tmp_csar_dir):
        # NOTE: This method is not called by a userdata script but
        # is called by the openstack infra_driver directly now.
        # It is thought that it is suitable that this method defines
        # here since it is very likely to scale method above.

        vnfd = common_script_utils.get_vnfd(inst['vnfdId'], tmp_csar_dir)
        flavour_id = inst['instantiatedVnfInfo']['flavourId']

        hot_dict = vnfd.get_base_hot(flavour_id)
        top_hot = hot_dict['template']

        nfv_dict = common_script_utils.init_nfv_dict(top_hot)

        cps = nfv_dict.get('CP', {})
        new_cps = {}
        for cp_name, cp_value in cps.items():
            if 'network' in cp_value:
                network = common_script_utils.get_param_network_from_inst(
                    cp_name, inst)
                if network is None:
                    continue
                new_cps.setdefault(cp_name, {})
                new_cps[cp_name]['network'] = network
            if 'fixed_ips' in cp_value:
                ext_fixed_ips = (
                    common_script_utils.get_param_fixed_ips_from_inst(
                        cp_name, inst))
                fixed_ips = []
                for i in range(len(ext_fixed_ips)):
                    if i not in cp_value['fixed_ips']:
                        break
                    ips_i = cp_value['fixed_ips'][i]
                    if 'subnet' in ips_i:
                        ips_i['subnet'] = ext_fixed_ips[i].get('subnet')
                    if 'ip_address' in ips_i:
                        ips_i['ip_address'] = ext_fixed_ips[i].get(
                            'ip_address')
                    fixed_ips.append(ips_i)
                new_cps.setdefault(cp_name, {})
                new_cps[cp_name]['fixed_ips'] = fixed_ips

        fields = {'parameters': {'nfv': {'CP': new_cps}}}

        return fields

    @staticmethod
    def heal(req, inst, grant_req, grant, tmp_csar_dir):
        # It is not necessary to change parameters at heal basically.

        fields = {'parameters': {'nfv': {}}}

        return fields

The following is sample Base HOT corresponding to above sample userdata script.

top Base HOT

heat_template_version: 2013-05-23
description: 'Simple Base HOT for Sample VNF'

parameters:
  nfv:
    type: json

resources:
  VDU1_scale_group:
    type: OS::Heat::AutoScalingGroup
    properties:
      min_size: 1
      max_size: 3
      desired_capacity: { get_param: [ nfv, VDU, VDU1, desired_capacity ] }
      resource:
        type: VDU1.yaml
        properties:
          flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
          image: { get_param: [ nfv, VDU, VDU1-VirtualStorage, vcImageId ] }
          zone: { get_param: [ nfv, VDU, VDU1, locationConstraints] }
          net1: { get_param: [ nfv, CP, VDU1_CP1, network] }
          net2: { get_param: [ nfv, CP, VDU1_CP2, network ] }
          subnet1: { get_param: [nfv, CP, VDU1_CP1, fixed_ips, 0, subnet ]}
          subnet2: { get_param: [nfv, CP, VDU1_CP2, fixed_ips, 0, subnet ]}
          net3: { get_resource: internalVL1 }
          net4: { get_resource: internalVL2 }
          net5: { get_resource: internalVL3 }

# NOTE: Resource definition of OS::Heat::ScalingPolicy is omitted.
# It is not used by v2 scale implementation unlike v1.

  VDU2:
    type: OS::Nova::Server
    properties:
      flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
      name: VDU2
      availability_zone: { get_param: [ nfv, VDU, VDU2, locationConstraints ] }
      block_device_mapping_v2: [{"volume_id": { get_resource: VDU2-VirtualStorage }}]
      networks:
      - port: { get_param: [ nfv, CP, VDU2_CP1-1, port ]  }
      - port: { get_param: [ nfv, CP, VDU2_CP1-2, port ]  }
      - port:
          get_resource: VDU2_CP2
      - port:
          get_resource: VDU2_CP3
      - port:
          get_resource: VDU2_CP4
      - port:
          get_resource: VDU2_CP5

  VDU2-VirtualStorage:
    type: OS::Cinder::Volume
    properties:
      image: { get_param: [ nfv, VDU, VDU2-VirtualStorage, vcImageId] }
      size: 1
      volume_type: { get_resource: multi }
  multi:
    type: OS::Cinder::VolumeType
    properties:
      name: VDU2-multi
      metadata: { multiattach: "<is> True" }

# extVL with FixedIP and Subnet
  VDU2_CP2:
    type: OS::Neutron::Port
    properties:
      network: { get_param: [ nfv, CP, VDU2_CP2, network ]  }
      fixed_ips:
      - ip_address: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, ip_address]}
        subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, subnet]}
      - subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 1, subnet]}

  VDU2_CP3:
    type: OS::Neutron::Port
    properties:
# replace the following line to VL's ID when extmanagedVLs are specified in instantiatevnfrequest
      network: { get_resource: internalVL1 }

  VDU2_CP4:
    type: OS::Neutron::Port
    properties:
# replace the following line to VL's ID when extmanagedVLs are specified in instantiatevnfrequest
      network: { get_resource: internalVL2 }

  VDU2_CP5:
    type: OS::Neutron::Port
    properties:
# replace the following line to VL's ID when extmanagedVLs are specified in instantiatevnfrequest
      network: { get_resource: internalVL3 }

# delete the following lines when extmanagedVLs are specified in instantiatevnfrequest
  internalVL1:
    type: OS::Neutron::Net
  internalVL2:
    type: OS::Neutron::Net
  internalVL3:
    type: OS::Neutron::Net

  internalVL1_subnet:
    type: OS::Neutron::Subnet
    properties:
      ip_version: 4
      network:
        get_resource: internalVL1
      cidr: 192.168.3.0/24
  internalVL2_subnet:
    type: OS::Neutron::Subnet
    properties:
      ip_version: 4
      network:
        get_resource: internalVL2
      cidr: 192.168.4.0/24
  internalVL3_subnet:
    type: OS::Neutron::Subnet
    properties:
      ip_version: 4
      network:
        get_resource: internalVL3
      cidr: 192.168.5.0/24
outputs: {}

nested Base HOT

heat_template_version: 2013-05-23
description: 'VDU1 HOT for Sample VNF'

parameters:
  flavor:
    type: string
  image:
    type: string
  zone:
    type: string
  net1:
    type: string
  net2:
    type: string
  net3:
    type: string
  net4:
    type: string
  net5:
    type: string
  subnet1:
    type: string
  subnet2:
    type: string

resources:
  VDU1:
    type: OS::Nova::Server
    properties:
      flavor: { get_param: flavor }
      name: VDU1
      block_device_mapping_v2: [{"volume_id": { get_resource: VDU1-VirtualStorage }}]
      networks:
      - port:
          get_resource: VDU1_CP1
      - port:
          get_resource: VDU1_CP2
# replace the following line to Port ID when extmanagedVLs' Ports are specified in instantiatevnfrequest
      - port:
          get_resource: VDU1_CP3
      - port:
          get_resource: VDU1_CP4
      - port:
          get_resource: VDU1_CP5


      availability_zone: { get_param: zone }

  VDU1-VirtualStorage:
    type: OS::Cinder::Volume
    properties:
      image: { get_param: image }
      size: 1
      volume_type: { get_resource: multi }
  multi:
    type: OS::Cinder::VolumeType
    properties:
      name: { get_resource: VDU1_CP1 }
      metadata: { multiattach: "<is> True" }

# extVL without FixedIP or with numDynamicAddresses
  VDU1_CP1:
    type: OS::Neutron::Port
    properties:
      network: { get_param: net1 }
      fixed_ips:
      - subnet: { get_param: subnet1}

# extVL with numDynamicAddresses and subnet
  VDU1_CP2:
    type: OS::Neutron::Port
    properties:
      network: { get_param: net2 }
      fixed_ips:
      - subnet: { get_param: subnet2}

# delete the following line when extmanagedVLs' Ports are specified in instantiatevnfrequest
  VDU1_CP3:
    type: OS::Neutron::Port
    properties:
      network: { get_param: net3 }

  VDU1_CP4:
    type: OS::Neutron::Port
    properties:
      network: { get_param: net4 }

  VDU1_CP5:
    type: OS::Neutron::Port
    properties:
      network: { get_param: net5 }

Utility functions for userdata class

Tacker provides the following utility functions for the userdata script. Following functions can be called in userdata class.

def get_vnfd(vnfd_id, csar_dir)

Get vnfd in yaml format.

vnf_id: vnfid , csar_dir: the path of csar.

It returns an instance of **Vnfd** class.

def init_nfv_dict(hot_template)

Find the parameter specified by get_param in the HOT template and get the dict of the nfv structure for the HEAT input parameter.

hot_template: HOT in yaml format.

It returns the dict of nfv structure.

def get_param_flavor(vdu_name, req, vnfd, grant)

Get flavor of VDU. If Grant contains the flavor, it is returned. Otherwise, flavor is obtained from vnfd and returned.

vdu_name: the name of VDU , req: InstantiateVnfRequest , vnfd: vnfd , grant: Grants

It returns vimFlavourId

def get_param_image(vdu_name, req, vnfd, grant)

Get software image of VDU. If Grant contains the glance-imageId corresponding to the VDU, it is returned. Otherwise, name of software image is obtained from vnfd and returned.

vdu_name: the name of VDU , req: InstantiateVnfRequest , vnfd: vnfd , grant: Grants

It returns image ID or image name.

def get_param_zone(vdu_name, grant_req, grant)

Get zone id of VDU.

vdu_name: the name of VDU , req: InstantiateVnfRequest , vnfd: vnfd , grant: Grants

It returns zone id.

def get_current_capacity(vdu_name, inst)

Get desired capacity.

vdu_name: the name of VDU , inst: VnfInstance

It returns desired capacity.

def get_param_capacity(vdu_name, inst, grant_req)

Refer to addResources and removeResources in the grant request and get desired capacity.

vdu_name: the name of VDU , inst: VnfInstance , grant_req: GrantRequest

It returns desired capacity.

def _get_fixed_ips_from_extcp(extcp)

Get list of fixed address and subnet from extcp. extcp is instantiateVnfRequest > extVirtualLinks > extcps defined in ETSI NFV SOL003.

It returns the list of fixed address and subnet.

def get_param_network(cp_name, grant, req)

Get network resourceId of CP.

cp_name: the name of CP , grant: Grants , req: InstantiateVnfRequest

It returns network resourceId.

def get_param_fixed_ips(cp_name, grant, req)

Get fixed IP addresses of CP.

cp_name: the name of CP , grant: Grants , req: InstantiateVnfRequest

It returns fixed IP address of CP.

def get_param_network_from_inst(cp_name, inst)

Get network resourceId from VnfInstance.

cp_name: the name of CP , inst: VnfInstance

It returns network resourceId from VnfInstance.

def get_param_fixed_ips_from_inst(cp_name, inst)

Get fixed IP address of CP from VnfInstance.

cp_name: the name of CP , inst: VnfInstance

It returns fixed IP address of CP from VnfInstance.

def apply_ext_managed_vls(hot_dict, req, grant)

Modify HOT to apply externally provided extmanaged internal virtual link (extmanagedVL).

ExtmanagedVL is created by VNFM when instantiating VNF or externally created and specified by Grants or InstantiateVnfRequest. Since one HOT can correspond to only one of the cases, this function modifies HOT for the former case to for the latter case.

The Following shows the sample HOT description.

  • Input HOT

heat_template_version: 2013-05-23
description: 'Simple Base HOT for Sample VNF'

resources:
  VDU1:
    type: OS::Nova::Server
    properties:
      flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
      image: { get_param: [ nfv, VDU, VDU2, vcImageId] }
      networks:
      - port:
          get_resource: VDU1_CP1

  VDU1_CP1:
    type: OS::Neutron::Port
    properties:
      network: { get_resource: internalVL1 }

  internalVL1:
    type: OS::Neutron::Net

outputs: {}
  • Output HOT

heat_template_version: 2013-05-23
description: 'Simple Base HOT for Sample VNF'

resources:
  VDU1:
    type: OS::Nova::Server
    properties:
      flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
      image: { get_param: [ nfv, VDU, VDU2, vcImageId] }
      networks:
      - port:
          get_resource: VDU1_CP1


  VDU1_CP1:
    type: OS::Neutron::Port
    properties:
      network: network_id

outputs: {}

vnfd.get_base_hot(flavour_id)

Get HOT dict.

flavour_id: flavour_id of vnf instance.

It returns HOT dict with the following structure. dict = {‘template’:tophot, ‘Files’{file 1:, file2:…}}

vnf_instance_utils.json_merge_patch(target, patch)

Get the result of json_merge_patch (IETF RFC 7396).

target: merge target , patch: applied patch

It returns the result of json_merge_patch (IETF RFC 7396).