tacker/tacker/sol_refactored/infra_drivers/openstack/userdata_utils.py

217 lines
7.2 KiB
Python

# 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 abc
from tacker.sol_refactored.common import exceptions as sol_ex
from tacker.sol_refactored.common import vnfd_utils
class AbstractUserData(metaclass=abc.ABCMeta):
@staticmethod
@abc.abstractmethod
def instantiate(req, inst, grant_req, grant, tmp_csar_dir):
"""Definition of instantiate method
Args:
req: InstantiateVnfRequest dict
inst: VnfInstance dict
grant_req: GrantRequest dict
grant: Grant dict
tmp_csar_dir: directory path that csar contents are extracted
Returns:
dict of parameters for create heat stack.
see the example of userdata_default.py.
"""
raise sol_ex.UserDataClassNotImplemented()
def get_vnfd(vnfd_id, csar_dir):
vnfd = vnfd_utils.Vnfd(vnfd_id)
vnfd.init_from_csar_dir(csar_dir)
return vnfd
def init_nfv_dict(hot_template):
get_params = []
def _get_get_param(prop):
if isinstance(prop, dict):
for key, value in prop.items():
if key == 'get_param':
get_params.append(value)
else:
_get_get_param(value)
elif isinstance(prop, list):
for value in prop:
_get_get_param(value)
for res in hot_template.get('resources', {}).values():
_get_get_param(res.get('properties', {}))
nfv = {}
for param in get_params:
if (not isinstance(param, list) or len(param) < 4 or
param[0] != 'nfv'):
continue
parent = nfv
for item in param[1:-1]:
parent.setdefault(item, {})
parent = parent[item]
parent[param[-1]] = None
# TODO(oda-g): enhance to handle list
# NOTE: List is not considered here and only 'fixed_ips' is treated as
# list in userdata_default.py at the moment.
# Note that if handling list is enhanced, userdata_default.py is
# necessary to modify.
return nfv
def get_param_flavor(vdu_name, req, vnfd, grant):
# try to get from grant
if 'vimAssets' in grant:
assets = grant['vimAssets']
if 'computeResourceFlavours' in assets:
flavours = assets['computeResourceFlavours']
for flavour in flavours:
if flavour['vnfdVirtualComputeDescId'] == vdu_name:
return flavour['vimFlavourId']
# if specified in VNFD, use it
# NOTE: if not found. parameter is set to None.
# may be error when stack create
return vnfd.get_compute_flavor(req['flavourId'], vdu_name)
def get_param_image(vdu_name, req, vnfd, grant):
# try to get from grant
if 'vimAssets' in grant:
assets = grant['vimAssets']
if 'softwareImages' in assets:
images = assets['softwareImages']
for image in images:
if image['vnfdSoftwareImageId'] == vdu_name:
return image['vimSoftwareImageId']
# if specified in VNFD, use it
# NOTE: if not found. parameter is set to None.
# may be error when stack create
sw_images = vnfd.get_sw_image(req['flavourId'])
for name, image in sw_images.items():
if name == vdu_name:
return image
def get_param_zone(vdu_name, grant_req, grant):
if 'zones' not in grant or 'addResources' not in grant:
return
for res in grant['addResources']:
if 'zoneId' not in res:
continue
for req_res in grant_req['addResources']:
if req_res['id'] == res['resourceDefinitionId']:
if req_res.get('resourceTemplateId') == vdu_name:
for zone in grant['zones']:
if zone['id'] == res['zoneId']: # must be found
return zone['zoneId']
def _get_fixed_ips_from_extcp(extcp):
fixed_ips = []
for cp_conf in extcp['cpConfig'].values():
if 'cpProtocolData' not in cp_conf:
continue
for prot_data in cp_conf['cpProtocolData']:
if 'ipOverEthernet' not in prot_data:
continue
if 'ipAddresses' not in prot_data['ipOverEthernet']:
continue
for ip in prot_data['ipOverEthernet']['ipAddresses']:
data = {}
if 'fixedAddresses' in ip:
# pick up only one ip address
data['ip_address'] = str(ip['fixedAddresses'][0])
if 'subnetId' in ip:
data['subnet'] = ip['subnetId']
if data:
fixed_ips.append(data)
return fixed_ips
def get_param_network(cp_name, grant, req):
# see grant first then instantiateVnfRequest
vls = grant.get('extVirtualLinks', []) + req.get('extVirtualLinks', [])
for vl in vls:
for extcp in vl['extCps']:
if extcp['cpdId'] == cp_name:
return vl['resourceId']
def get_param_fixed_ips(cp_name, grant, req):
# see grant first then instantiateVnfRequest
vls = grant.get('extVirtualLinks', []) + req.get('extVirtualLinks', [])
for vl in vls:
for extcp in vl['extCps']:
if extcp['cpdId'] == cp_name:
return _get_fixed_ips_from_extcp(extcp)
def apply_ext_managed_vls(hot_dict, req, grant):
# see grant first then instantiateVnfRequest
mgd_vls = (grant.get('extManagedVirtualLinks', []) +
req.get('extManagedVirtualLinks', []))
# NOTE: refer HOT only here, not refer VNFD.
# HOT and VNFD must be consistent.
for mgd_vl in mgd_vls:
vl_name = mgd_vl['vnfVirtualLinkDescId']
network_id = mgd_vl['resourceId']
get_res = {'get_resource': vl_name}
def _change(item):
if not isinstance(item, dict):
return
for key, value in item.items():
if value == get_res:
item[key] = network_id
else:
_change(value)
del_reses = []
for res_name, res_data in hot_dict.get('resources', {}).items():
# delete network definition
if res_name == vl_name:
del_reses.append(res_name)
# delete subnet definition
if res_data['type'] == 'OS::Neutron::Subnet':
net = (res_data.get('properties', {})
.get('network', {})
.get('get_resource'))
if net == vl_name:
del_reses.append(res_name)
# change '{get_resource: vl_name}' to network_id
_change(res_data)
for res_name in del_reses:
hot_dict['resources'].pop(res_name)