Support for grant request with Synchronous response
Supported grant for the following sequences: Instantiation Healing Scaling Termination Implements: blueprint support-vnfm-operations Spec: https://specs.openstack.org/openstack/tacker-specs/specs/victoria/support-sol003-vnfm-operations.html Change-Id: I47a6a995dc25256eb1bd10f2e03a1f810fdb3f69
This commit is contained in:
parent
49be782dc2
commit
ffe4c40921
@ -455,7 +455,7 @@ class VnfLcmController(wsgi.Controller):
|
||||
'vnfInstance': {
|
||||
'href': self._get_vnf_instance_href(vnf_instance)}}}
|
||||
|
||||
# call sendNotification
|
||||
# call send_notification
|
||||
self.rpc_api.send_notification(context, notification)
|
||||
|
||||
result = self._view_builder.create(vnf_instance)
|
||||
|
@ -25,7 +25,6 @@ import time
|
||||
import traceback
|
||||
import yaml
|
||||
|
||||
|
||||
from glance_store import exceptions as store_exceptions
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
@ -51,6 +50,7 @@ from tacker.common import utils
|
||||
import tacker.conf
|
||||
from tacker import context as t_context
|
||||
from tacker.db.common_services import common_services_db
|
||||
from tacker.db.db_sqlalchemy import models
|
||||
from tacker.db.nfvo import nfvo_db
|
||||
from tacker.db.vnfm import vnfm_db
|
||||
from tacker.extensions import nfvo
|
||||
@ -66,6 +66,7 @@ from tacker import service as tacker_service
|
||||
from tacker import version
|
||||
from tacker.vnflcm import utils as vnflcm_utils
|
||||
from tacker.vnflcm import vnflcm_driver
|
||||
from tacker.vnfm import nfvo_client
|
||||
from tacker.vnfm import plugin
|
||||
|
||||
CONF = tacker.conf.CONF
|
||||
@ -230,6 +231,65 @@ def revert_update_lcm(function):
|
||||
return decorated_function
|
||||
|
||||
|
||||
@utils.expects_func_args('vnf_instance', 'vnf_lcm_op_occ_id')
|
||||
def grant_error_common(function):
|
||||
"""Decorator to revert upload_vnf_package on failure."""
|
||||
|
||||
@functools.wraps(function)
|
||||
def decorated_function(self, context, *args, **kwargs):
|
||||
try:
|
||||
return function(self, context, *args, **kwargs)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
wrapped_func = safe_utils.get_wrapped_function(function)
|
||||
keyed_args = inspect.getcallargs(wrapped_func, self, context,
|
||||
*args, **kwargs)
|
||||
context = keyed_args['context']
|
||||
vnf_instance = keyed_args['vnf_instance']
|
||||
vnf_lcm_op_occ_id = keyed_args['vnf_lcm_op_occ_id']
|
||||
try:
|
||||
vnf_lcm_op_occs = objects.VnfLcmOpOcc.get_by_id(
|
||||
context, vnf_lcm_op_occ_id)
|
||||
timestamp = datetime.datetime.utcnow()
|
||||
vnf_lcm_op_occs.operation_state = 'ROLLED_BACK'
|
||||
vnf_lcm_op_occs.state_entered_time = timestamp
|
||||
vnf_lcm_op_occs.save()
|
||||
except Exception as e:
|
||||
LOG.warning("Failed to update vnf_lcm_op_occ for vnf "
|
||||
"instance %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id, "error": e})
|
||||
|
||||
try:
|
||||
notification = {}
|
||||
notification['notificationType'] = \
|
||||
'VnfLcmOperationOccurrenceNotification'
|
||||
notification['vnfInstanceId'] = vnf_instance.id
|
||||
notification['notificationStatus'] = 'RESULT'
|
||||
notification['operation'] = vnf_lcm_op_occs.operation
|
||||
notification['operationState'] = 'ROLLED_BACK'
|
||||
notification['isAutomaticInvocation'] = \
|
||||
vnf_lcm_op_occs.is_automatic_invocation
|
||||
notification['vnfLcmOpOccId'] = vnf_lcm_op_occ_id
|
||||
insta_url = CONF.vnf_lcm.endpoint_url + \
|
||||
"/vnflcm/v1/vnf_instances/" + \
|
||||
vnf_instance.id
|
||||
vnflcm_url = CONF.vnf_lcm.endpoint_url + \
|
||||
"/vnflcm/v1/vnf_lcm_op_occs/" + \
|
||||
vnf_lcm_op_occ_id
|
||||
notification['_links'] = {}
|
||||
notification['_links']['vnfInstance'] = {}
|
||||
notification['_links']['vnfInstance']['href'] = insta_url
|
||||
notification['_links']['vnfLcmOpOcc'] = {}
|
||||
notification['_links']['vnfLcmOpOcc']['href'] = vnflcm_url
|
||||
self.send_notification(context, notification)
|
||||
except Exception as e:
|
||||
LOG.warning("Failed notification for vnf "
|
||||
"instance %(id)s. Error: %(error)s",
|
||||
{"id": vnf_instance.id, "error": e})
|
||||
|
||||
return decorated_function
|
||||
|
||||
|
||||
class Conductor(manager.Manager):
|
||||
def __init__(self, host, conf=None):
|
||||
if conf:
|
||||
@ -661,8 +721,9 @@ class Conductor(manager.Manager):
|
||||
vim_connection_info = objects.VimConnectionInfo.\
|
||||
obj_from_primitive(vim_info, context)
|
||||
|
||||
vnflcm_utils._build_instantiated_vnf_info(vnfd_dict,
|
||||
instantiate_vnf_req, vnf_instance,
|
||||
if not vnf_instance.instantiated_vnf_info.instance_id:
|
||||
vnflcm_utils._build_instantiated_vnf_info(
|
||||
vnfd_dict, instantiate_vnf_req, vnf_instance,
|
||||
vim_id=vim_connection_info.vim_id)
|
||||
|
||||
if vnf_instance.instantiated_vnf_info.instance_id:
|
||||
@ -761,6 +822,522 @@ class Conductor(manager.Manager):
|
||||
{'zip': csar_path, 'folder': csar_zip_temp_path,
|
||||
'uuid': vnf_pack.id})
|
||||
|
||||
def _grant(self, context, grant_request):
|
||||
LOG.info(
|
||||
"grant start grant_request[%s]" %
|
||||
grant_request.to_request_body())
|
||||
|
||||
response = nfvo_client.GrantRequest().grants(
|
||||
json=grant_request.to_request_body())
|
||||
|
||||
res_body = response.json()
|
||||
res_dict = utils.convert_camelcase_to_snakecase(res_body)
|
||||
LOG.info("grant end res_body[%s]" % res_dict)
|
||||
grant_obj = objects.Grant.obj_from_primitive(
|
||||
res_dict, context=context)
|
||||
if len(grant_request.add_resources) != len(grant_obj.add_resources):
|
||||
msg = "grant add resource error"
|
||||
raise exceptions.ValidationError(detail=msg)
|
||||
if len(
|
||||
grant_request.remove_resources) != len(
|
||||
grant_obj.remove_resources):
|
||||
msg = "grant remove resource error"
|
||||
raise exceptions.ValidationError(detail=msg)
|
||||
|
||||
self._check_res_add_remove_rsc(context, grant_request, grant_obj)
|
||||
|
||||
return grant_obj
|
||||
|
||||
def _check_res_add_remove_rsc(self, context, grant_request, grant_obj):
|
||||
for add_resource in grant_request.add_resources:
|
||||
match_flg = False
|
||||
for rsc in grant_obj.add_resources:
|
||||
if add_resource.id == rsc.resource_definition_id:
|
||||
match_flg = True
|
||||
break
|
||||
if not match_flg:
|
||||
msg = "grant add resource error"
|
||||
raise exceptions.ValidationError(detail=msg)
|
||||
|
||||
for remove_resource in grant_request.remove_resources:
|
||||
match_flg = False
|
||||
for rsc in grant_obj.remove_resources:
|
||||
if remove_resource.id == rsc.resource_definition_id:
|
||||
match_flg = True
|
||||
break
|
||||
if not match_flg:
|
||||
msg = "grant remove resource error"
|
||||
raise exceptions.ValidationError(detail=msg)
|
||||
|
||||
@grant_error_common
|
||||
def _instantiate_grant(self,
|
||||
context,
|
||||
vnf_instance,
|
||||
vnf_dict,
|
||||
instantiate_vnf_request,
|
||||
vnf_lcm_op_occ_id):
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(context,
|
||||
vnf_dict['vnfd']['id'],
|
||||
instantiate_vnf_request.flavour_id)
|
||||
inst_level = instantiate_vnf_request.instantiation_level_id
|
||||
vnf_instance.instantiated_vnf_info = objects.InstantiatedVnfInfo(
|
||||
flavour_id=instantiate_vnf_request.flavour_id,
|
||||
instantiation_level_id=inst_level,
|
||||
vnf_instance_id=vnf_instance.id)
|
||||
vnf_instance.instantiated_vnf_info.reinitialize()
|
||||
vnflcm_utils._build_instantiated_vnf_info(vnfd_dict,
|
||||
instantiate_vnf_request, vnf_instance, '')
|
||||
if not self._get_grant_execute():
|
||||
return
|
||||
|
||||
add_resources = []
|
||||
vnf_inf = vnf_instance.instantiated_vnf_info
|
||||
for vnfc_resource in vnf_inf.vnfc_resource_info:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = vnfc_resource.id
|
||||
resource.type = constants.TYPE_COMPUTE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = vnfc_resource.vdu_id
|
||||
add_resources.append(resource)
|
||||
|
||||
for vl_resource in vnf_inf.vnf_virtual_link_resource_info:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = vl_resource.id
|
||||
resource.type = constants.TYPE_VL
|
||||
resource.resource_template_id = \
|
||||
vl_resource.vnf_virtual_link_desc_id
|
||||
add_resources.append(resource)
|
||||
for cp_resource in vl_resource.vnf_link_ports:
|
||||
for vnfc_resource in vnf_inf.vnfc_resource_info:
|
||||
for vnfc_cp_resource in vnfc_resource.vnfc_cp_info:
|
||||
if cp_resource.cp_instance_id == vnfc_cp_resource.id:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = cp_resource.id
|
||||
resource.type = constants.TYPE_LINKPORT
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = \
|
||||
vnfc_cp_resource.cpd_id
|
||||
add_resources.append(resource)
|
||||
|
||||
for storage_resource in vnf_inf.virtual_storage_resource_info:
|
||||
for vnfc_resource in vnf_inf.vnfc_resource_info:
|
||||
if storage_resource.id in vnfc_resource.storage_resource_ids:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = storage_resource.id
|
||||
resource.type = constants.TYPE_STORAGE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = \
|
||||
storage_resource.virtual_storage_desc_id
|
||||
add_resources.append(resource)
|
||||
|
||||
p_c_list = []
|
||||
placement_obj_list = []
|
||||
topo_temp = vnfd_dict.get('topology_template', {})
|
||||
for policy in topo_temp.get('policies', []):
|
||||
for policy_name, policy_dict in policy.items():
|
||||
key_type = 'tosca.policies.nfv.AntiAffinityRule'
|
||||
if policy_dict['type'] == key_type:
|
||||
placement_constraint = objects.PlacementConstraint()
|
||||
placement_constraint.affinity_or_anti_affinity = \
|
||||
'ANTI_AFFINITY'
|
||||
placement_constraint.scope = 'ZONE'
|
||||
placement_constraint.resource = []
|
||||
placement_constraint.fallback_best_effort = True
|
||||
for target in policy_dict.get('targets', []):
|
||||
if target in topo_temp.get('groups', []):
|
||||
for member in topo_temp['groups']['members']:
|
||||
for vnfc_rsc in vnf_inf.vnfc_resource_info:
|
||||
if member == vnfc_rsc.vdu_id:
|
||||
resource = \
|
||||
objects.ConstraintResourceRef()
|
||||
resource.id_type = 'GRANT'
|
||||
resource.resource_id = vnfc_rsc.id
|
||||
p_rsc = \
|
||||
placement_constraint.resource
|
||||
p_rsc.append(resource)
|
||||
break
|
||||
else:
|
||||
for vnfc_rsc in vnf_inf.vnfc_resource_info:
|
||||
if target == vnfc_rsc.vdu_id:
|
||||
resource = \
|
||||
objects.ConstraintResourceRef()
|
||||
resource.id_type = 'GRANT'
|
||||
resource.resource_id = vnfc_rsc.id
|
||||
p_rsc = placement_constraint.resource
|
||||
p_rsc.append(resource)
|
||||
break
|
||||
p_c_list.append(placement_constraint)
|
||||
placement_obj = models.PlacementConstraint()
|
||||
placement_obj.id = uuidutils.generate_uuid()
|
||||
placement_obj.vnf_instance_id = vnf_instance.id
|
||||
placement_obj.affinity_or_anti_affinity = \
|
||||
placement_constraint.affinity_or_anti_affinity
|
||||
placement_obj.scope = placement_constraint.scope
|
||||
placement_obj.server_group_name = policy_name
|
||||
p_c_dict = placement_constraint.to_dict()
|
||||
res_dict = p_c_dict.get('resource', {})
|
||||
res_json = json.dumps(res_dict)
|
||||
placement_obj.resource = res_json
|
||||
placement_obj.created_at = timeutils.utcnow()
|
||||
placement_obj.deleted_at = datetime.datetime.min
|
||||
placement_obj_list.append(placement_obj)
|
||||
|
||||
g_request = self._make_grant_request(context,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occ_id,
|
||||
'INSTANTIATE',
|
||||
False,
|
||||
add_resources=add_resources,
|
||||
placement_constraints=p_c_list)
|
||||
|
||||
vnf_dict['placement_obj_list'] = placement_obj_list
|
||||
vnf_dict['grant'] = self._grant(context, g_request)
|
||||
|
||||
def _get_placement(self, context, vnf_instance):
|
||||
return self.vnfm_plugin.get_placement_constraint(context,
|
||||
vnf_instance.id)
|
||||
|
||||
@grant_error_common
|
||||
def _scale_grant(
|
||||
self,
|
||||
context,
|
||||
vnf_dict,
|
||||
vnf_instance,
|
||||
scale_vnf_request,
|
||||
vnf_lcm_op_occ_id):
|
||||
# Check if vnf is in instantiated state.
|
||||
vnf_instance = objects.VnfInstance.get_by_id(context,
|
||||
vnf_instance.id)
|
||||
if vnf_instance.instantiation_state == \
|
||||
fields.VnfInstanceState.NOT_INSTANTIATED:
|
||||
LOG.error("Scale action cannot be performed on vnf %(id)s "
|
||||
"which is in %(state)s state.",
|
||||
{"id": vnf_instance.id,
|
||||
"state": vnf_instance.instantiation_state})
|
||||
raise Exception("Scale action cannot be performed on vnf")
|
||||
|
||||
vim_info = vnflcm_utils._get_vim(
|
||||
context, vnf_instance.vim_connection_info)
|
||||
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
|
||||
vim_info, context)
|
||||
if scale_vnf_request.type == 'SCALE_IN':
|
||||
vnf_dict['action'] = 'in'
|
||||
reverse = scale_vnf_request.additional_params.get('is_reverse')
|
||||
region_name = vim_connection_info.access_info.get('region_name')
|
||||
scale_id_list, scale_name_list, grp_id, res_num = \
|
||||
self.vnf_manager.invoke(vim_connection_info.vim_type,
|
||||
'get_scale_in_ids',
|
||||
plugin=self,
|
||||
context=context,
|
||||
vnf_dict=vnf_dict,
|
||||
is_reverse=reverse,
|
||||
auth_attr=vim_connection_info.access_info,
|
||||
region_name=region_name,
|
||||
number_of_steps=scale_vnf_request.number_of_steps)
|
||||
vnf_dict['res_num'] = res_num
|
||||
else:
|
||||
scale_id_list = []
|
||||
if not self._get_grant_execute():
|
||||
return None, []
|
||||
|
||||
placement_obj_list = self.vnfm_plugin.get_placement_constraint(
|
||||
context, vnf_instance.id)
|
||||
self.vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'get_grant_resource',
|
||||
plugin=self,
|
||||
vnf_instance=vnf_instance,
|
||||
vnf_info=vnf_dict,
|
||||
scale_vnf_request=scale_vnf_request,
|
||||
placement_obj_list=placement_obj_list,
|
||||
vim_connection_info=vim_connection_info,
|
||||
del_list=scale_id_list
|
||||
)
|
||||
vnf_dict['placement_obj_list'] = placement_obj_list
|
||||
|
||||
grant_request = self._make_grant_request(
|
||||
context,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occ_id,
|
||||
'SCALE',
|
||||
False,
|
||||
add_resources=vnf_dict['addResources'],
|
||||
remove_resources=vnf_dict['removeResources'],
|
||||
placement_constraints=vnf_dict['placement_constraint_list'])
|
||||
|
||||
vnf_dict['grant'] = self._grant(context, grant_request)
|
||||
|
||||
@grant_error_common
|
||||
def _heal_grant(self,
|
||||
context,
|
||||
vnf_instance,
|
||||
vnf_dict,
|
||||
heal_vnf_request,
|
||||
vnf_lcm_op_occ_id):
|
||||
vnf_inf = vnf_instance.instantiated_vnf_info
|
||||
if not self._get_grant_execute():
|
||||
return
|
||||
|
||||
placement_obj_list = self._get_placement(context, vnf_instance)
|
||||
vim_info = vnflcm_utils._get_vim(context,
|
||||
vnf_instance.vim_connection_info)
|
||||
vim_connection_info = \
|
||||
objects.VimConnectionInfo.obj_from_primitive(vim_info, context)
|
||||
|
||||
cinder_list = self.vnf_manager.invoke(vim_connection_info.vim_type,
|
||||
'get_cinder_list',
|
||||
vnf_info=vnf_dict)
|
||||
|
||||
vnf_instantiated_info_after = copy.deepcopy(vnf_inf)
|
||||
del_cre_vdu_list = []
|
||||
add_resources = []
|
||||
rm_resources = []
|
||||
affinity_list = []
|
||||
for vnfc_resource in vnf_instantiated_info_after.vnfc_resource_info:
|
||||
vnfc_key = vnfc_resource.compute_resource.resource_id
|
||||
if not heal_vnf_request.vnfc_instance_id or \
|
||||
vnfc_key in heal_vnf_request.vnfc_instance_id:
|
||||
if vnfc_resource.vdu_id not in del_cre_vdu_list:
|
||||
del_cre_vdu_list.append(vnfc_resource.vdu_id)
|
||||
for vnfc_resource in vnf_instantiated_info_after.vnfc_resource_info:
|
||||
if vnfc_resource.vdu_id in del_cre_vdu_list:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = vnfc_resource.id
|
||||
resource.type = constants.TYPE_COMPUTE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = vnfc_resource.vdu_id
|
||||
vim_id = vnfc_resource.compute_resource.vim_connection_id
|
||||
rsc_id = vnfc_resource.compute_resource.resource_id
|
||||
vnfc_rh = objects.ResourceHandle(
|
||||
vim_connection_id=vim_id,
|
||||
resource_id=rsc_id)
|
||||
resource.resource = vnfc_rh
|
||||
rm_resources.append(resource)
|
||||
add_uuid = uuidutils.generate_uuid()
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = add_uuid
|
||||
resource.type = constants.TYPE_COMPUTE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = vnfc_resource.vdu_id
|
||||
add_resources.append(resource)
|
||||
|
||||
key_id = vnfc_resource.compute_resource.resource_id
|
||||
for placement_obj in placement_obj_list:
|
||||
resource_dict = jsonutils.loads(placement_obj.resource)
|
||||
set_flg = False
|
||||
for resource in resource_dict:
|
||||
if resource.get('resource_id') == key_id:
|
||||
resource['id_type'] = 'GRANT'
|
||||
resource['resource_id'] = add_uuid
|
||||
g_name = placement_obj.server_group_name
|
||||
affinity_list.append(g_name)
|
||||
set_flg = True
|
||||
res_json = jsonutils.dump_as_bytes(resource_dict)
|
||||
placement_obj.resource = res_json
|
||||
break
|
||||
if set_flg:
|
||||
break
|
||||
vnfc_resource.id = add_uuid
|
||||
vnfc_resource.compute_resource = objects.ResourceHandle()
|
||||
|
||||
st_info = vnf_instantiated_info_after.virtual_storage_resource_info
|
||||
for storage_resource in st_info:
|
||||
if storage_resource.virtual_storage_desc_id in cinder_list:
|
||||
for vnfc_resource in vnf_inf.vnfc_resource_info:
|
||||
id_list = vnfc_resource.storage_resource_ids
|
||||
if storage_resource.id in id_list:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = storage_resource.id
|
||||
resource.type = constants.TYPE_STORAGE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = \
|
||||
storage_resource.virtual_storage_desc_id
|
||||
st_rh = objects.ResourceHandle()
|
||||
st_rh.vim_connection_id = \
|
||||
storage_resource.storage_resource.vim_connection_id
|
||||
st_rh.resource_id = \
|
||||
storage_resource.storage_resource.resource_id
|
||||
resource.resource = st_rh
|
||||
rm_resources.append(resource)
|
||||
|
||||
add_uuid = uuidutils.generate_uuid()
|
||||
resource = objects.ResourceDefinition()
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = add_uuid
|
||||
resource.type = constants.TYPE_STORAGE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = \
|
||||
storage_resource.virtual_storage_desc_id
|
||||
add_resources.append(resource)
|
||||
storage_resource.id = add_uuid
|
||||
storage_resource.storage_resource = \
|
||||
objects.ResourceHandle()
|
||||
|
||||
p_c_list = []
|
||||
for placement_obj in placement_obj_list:
|
||||
p_constraint = objects.PlacementConstraint()
|
||||
p_constraint.affinity_or_anti_affinity = \
|
||||
placement_obj.affinity_or_anti_affinity
|
||||
p_constraint.scope = placement_obj.scope
|
||||
resource_dict = jsonutils.loads(placement_obj.resource)
|
||||
p_constraint.resource = []
|
||||
for rsc in resource_dict:
|
||||
rsc_obj = objects.ConstraintResourceRef()
|
||||
rsc_obj.id_type = rsc.get('id_type')
|
||||
rsc_obj.resource_id = rsc.get('resource_id')
|
||||
p_constraint.resource.append(rsc_obj)
|
||||
p_constraint.fallback_best_effort = True
|
||||
p_c_list.append(p_constraint)
|
||||
|
||||
g_request = self._make_grant_request(context,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occ_id,
|
||||
'HEAL',
|
||||
False,
|
||||
add_resources=add_resources,
|
||||
remove_resources=rm_resources,
|
||||
placement_constraints=p_c_list)
|
||||
|
||||
vnf_dict['placement_obj_list'] = placement_obj_list
|
||||
vnf_dict['grant'] = self._grant(context, g_request)
|
||||
vnf_dict['vnf_instantiated_info_after'] = vnf_instantiated_info_after
|
||||
|
||||
@grant_error_common
|
||||
def _terminate_grant(self, context, vnf_instance, vnf_lcm_op_occ_id):
|
||||
vnf_inf = vnf_instance.instantiated_vnf_info
|
||||
if not self._get_grant_execute():
|
||||
return
|
||||
|
||||
rm_resources = []
|
||||
for vnfc_resource in vnf_inf.vnfc_resource_info:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = vnfc_resource.id
|
||||
resource.type = constants.TYPE_COMPUTE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = vnfc_resource.vdu_id
|
||||
vim_id = vnfc_resource.compute_resource.vim_connection_id
|
||||
rsc_id = vnfc_resource.compute_resource.resource_id
|
||||
vnfc_rh = objects.ResourceHandle(
|
||||
vim_connection_id=vim_id,
|
||||
resource_id=rsc_id)
|
||||
resource.resource = vnfc_rh
|
||||
rm_resources.append(resource)
|
||||
|
||||
for vl_resource in vnf_inf.vnf_virtual_link_resource_info:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = vl_resource.id
|
||||
resource.type = constants.TYPE_VL
|
||||
resource.resource_template_id = \
|
||||
vl_resource.vnf_virtual_link_desc_id
|
||||
vim_id = vl_resource.network_resource.vim_connection_id
|
||||
rsc_id = vl_resource.network_resource.resource_id
|
||||
vl_rh = objects.ResourceHandle(
|
||||
vim_connection_id=vim_id,
|
||||
resource_id=rsc_id)
|
||||
resource.resource = vl_rh
|
||||
rm_resources.append(resource)
|
||||
for cp_resource in vl_resource.vnf_link_ports:
|
||||
for vnfc_resource in vnf_inf.vnfc_resource_info:
|
||||
for vnfc_cp_resource in vnfc_resource.vnfc_cp_info:
|
||||
if cp_resource.cp_instance_id == vnfc_cp_resource.id:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = cp_resource.id
|
||||
resource.type = constants.TYPE_LINKPORT
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = \
|
||||
vnfc_cp_resource.cpd_id
|
||||
vim_id = \
|
||||
cp_resource.resource_handle.vim_connection_id
|
||||
rsc_id = cp_resource.resource_handle.resource_id
|
||||
cp_rh = objects.ResourceHandle(
|
||||
vim_connection_id=vim_id,
|
||||
resource_id=rsc_id)
|
||||
resource.resource = cp_rh
|
||||
rm_resources.append(resource)
|
||||
|
||||
for storage_resource in vnf_inf.virtual_storage_resource_info:
|
||||
for vnfc_resource in vnf_inf.vnfc_resource_info:
|
||||
if storage_resource.id in vnfc_resource.storage_resource_ids:
|
||||
resource = objects.ResourceDefinition()
|
||||
resource.id = storage_resource.id
|
||||
resource.type = constants.TYPE_STORAGE
|
||||
resource.vdu_id = vnfc_resource.vdu_id
|
||||
resource.resource_template_id = \
|
||||
storage_resource.virtual_storage_desc_id
|
||||
vim_id = \
|
||||
storage_resource.storage_resource.vim_connection_id
|
||||
rsc_id = storage_resource.storage_resource.resource_id
|
||||
st_rh = objects.ResourceHandle(
|
||||
vim_connection_id=vim_id,
|
||||
resource_id=rsc_id)
|
||||
resource.resource = st_rh
|
||||
rm_resources.append(resource)
|
||||
|
||||
grant_request = self._make_grant_request(context,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occ_id,
|
||||
'TERMINATE',
|
||||
False,
|
||||
remove_resources=rm_resources)
|
||||
self._grant(context, grant_request)
|
||||
|
||||
def _get_grant_execute(self):
|
||||
try:
|
||||
nfvo_client.GrantRequest().validate()
|
||||
except nfvo_client.UndefinedExternalSettingException:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _make_grant_request(self, context, vnf_instance,
|
||||
vnf_lcm_op_occ_id, operation,
|
||||
is_automatic_invocation,
|
||||
add_resources=[],
|
||||
remove_resources=[],
|
||||
placement_constraints=[]):
|
||||
grant_request = objects.GrantRequest()
|
||||
grant_request.vnf_instance_id = vnf_instance.id
|
||||
grant_request.vnf_lcm_op_occ_id = vnf_lcm_op_occ_id
|
||||
grant_request.vnfd_id = vnf_instance.vnfd_id
|
||||
grant_request.flavour_id = \
|
||||
vnf_instance.instantiated_vnf_info.flavour_id
|
||||
grant_request.operation = operation
|
||||
grant_request.is_automatic_invocation = is_automatic_invocation
|
||||
vnflcm_url = CONF.vnf_lcm.endpoint_url + \
|
||||
"/vnflcm/v1/vnf_lcm_op_occs/" + vnf_lcm_op_occ_id
|
||||
insta_url = CONF.vnf_lcm.endpoint_url + \
|
||||
"/vnflcm/v1/vnf_instances/" + vnf_instance.id
|
||||
link_vnflcm = objects.Link(href=vnflcm_url)
|
||||
link_insta = objects.Link(href=insta_url)
|
||||
link = objects.Links(vnf_lcm_op_occ=link_vnflcm,
|
||||
vnf_instance=link_insta)
|
||||
grant_request._links = link
|
||||
|
||||
if add_resources:
|
||||
grant_request.add_resources = add_resources
|
||||
if remove_resources:
|
||||
grant_request.remove_resources = remove_resources
|
||||
if placement_constraints:
|
||||
grant_request.placement_constraints = placement_constraints
|
||||
|
||||
return grant_request
|
||||
|
||||
def _create_placement(self, context, vnf_dict):
|
||||
p_list = vnf_dict.get('placement_obj_list', [])
|
||||
if len(p_list) == 0:
|
||||
return
|
||||
self.vnfm_plugin.create_placement_constraint(context,
|
||||
p_list)
|
||||
|
||||
def _update_placement(self, context, vnf_dict, vnf_instance):
|
||||
self.vnfm_plugin.update_placement_constraint(context,
|
||||
vnf_dict,
|
||||
vnf_instance)
|
||||
|
||||
def _delete_placement(self, context, vnf_instance_id):
|
||||
self.vnfm_plugin.delete_placement_constraint(context,
|
||||
vnf_instance_id)
|
||||
|
||||
@log.log
|
||||
def _get_vnf_notify(self, context, id):
|
||||
try:
|
||||
@ -790,6 +1367,7 @@ class Conductor(manager.Manager):
|
||||
is_automatic_invocation = \
|
||||
kwargs.get('is_automatic_invocation', False)
|
||||
error = kwargs.get('error', None)
|
||||
# Used for timing control when a failure occurs
|
||||
|
||||
if old_vnf_instance:
|
||||
vnf_instance_id = old_vnf_instance.id
|
||||
@ -918,7 +1496,7 @@ class Conductor(manager.Manager):
|
||||
self.__set_auth_subscription(line)
|
||||
|
||||
for num in range(CONF.vnf_lcm.retry_num):
|
||||
LOG.info("send notify[%s]" % json.dumps(notification))
|
||||
LOG.warn("send notify[%s]" % json.dumps(notification))
|
||||
auth_client = auth.auth_manager.get_auth_client(
|
||||
notification['subscriptionId'])
|
||||
response = auth_client.post(
|
||||
@ -965,6 +1543,12 @@ class Conductor(manager.Manager):
|
||||
instantiate_vnf,
|
||||
vnf_lcm_op_occs_id):
|
||||
|
||||
self._instantiate_grant(context,
|
||||
vnf_instance,
|
||||
vnf_dict,
|
||||
instantiate_vnf,
|
||||
vnf_lcm_op_occs_id)
|
||||
|
||||
try:
|
||||
# Update vnf_lcm_op_occs table and send notification "PROCESSING"
|
||||
self._send_lcm_op_occ_notification(
|
||||
@ -993,6 +1577,8 @@ class Conductor(manager.Manager):
|
||||
instantiation_state=fields.VnfInstanceState.
|
||||
INSTANTIATED, task_state=None)
|
||||
|
||||
self._create_placement(context, vnf_dict)
|
||||
|
||||
# Update vnf_lcm_op_occs table and send notification "COMPLETED"
|
||||
self._send_lcm_op_occ_notification(
|
||||
context=context,
|
||||
@ -1024,6 +1610,11 @@ class Conductor(manager.Manager):
|
||||
@coordination.synchronized('{vnf_instance[id]}')
|
||||
def terminate(self, context, vnf_lcm_op_occs_id,
|
||||
vnf_instance, terminate_vnf_req, vnf_dict):
|
||||
|
||||
self._terminate_grant(context,
|
||||
vnf_instance,
|
||||
vnf_lcm_op_occs_id)
|
||||
|
||||
try:
|
||||
old_vnf_instance = copy.deepcopy(vnf_instance)
|
||||
|
||||
@ -1042,6 +1633,9 @@ class Conductor(manager.Manager):
|
||||
|
||||
self.vnflcm_driver.terminate_vnf(context, vnf_instance,
|
||||
terminate_vnf_req)
|
||||
|
||||
self._delete_placement(context, vnf_instance.id)
|
||||
|
||||
self._change_vnf_status(context, vnf_instance.id,
|
||||
_PENDING_STATUS, 'INACTIVE')
|
||||
|
||||
@ -1086,6 +1680,12 @@ class Conductor(manager.Manager):
|
||||
heal_vnf_request,
|
||||
vnf_lcm_op_occs_id):
|
||||
|
||||
self._heal_grant(context,
|
||||
vnf_instance,
|
||||
vnf_dict,
|
||||
heal_vnf_request,
|
||||
vnf_lcm_op_occs_id)
|
||||
|
||||
try:
|
||||
old_vnf_instance = copy.deepcopy(vnf_instance)
|
||||
|
||||
@ -1117,6 +1717,8 @@ class Conductor(manager.Manager):
|
||||
self.vnflcm_driver._vnf_instance_update(context, vnf_instance,
|
||||
task_state=None)
|
||||
|
||||
self._update_placement(context, vnf_dict, vnf_instance)
|
||||
|
||||
# update vnf_lcm_op_occs and send notification "COMPLETED"
|
||||
self._send_lcm_op_occ_notification(
|
||||
context=context,
|
||||
@ -1150,16 +1752,15 @@ class Conductor(manager.Manager):
|
||||
|
||||
@coordination.synchronized('{vnf_instance[id]}')
|
||||
def scale(self, context, vnf_info, vnf_instance, scale_vnf_request):
|
||||
# Check if vnf is in instantiated state.
|
||||
vnf_instance = objects.VnfInstance.get_by_id(context,
|
||||
vnf_instance.id)
|
||||
if vnf_instance.instantiation_state == \
|
||||
fields.VnfInstanceState.NOT_INSTANTIATED:
|
||||
LOG.error("Scale action cannot be performed on vnf %(id)s "
|
||||
"which is in %(state)s state.",
|
||||
{"id": vnf_instance.id,
|
||||
"state": vnf_instance.instantiation_state})
|
||||
return
|
||||
vnf_lcm_op_occ = vnf_info['vnf_lcm_op_occ']
|
||||
vnf_lcm_op_occ_id = vnf_lcm_op_occ.id
|
||||
|
||||
self._scale_grant(
|
||||
context,
|
||||
vnf_info,
|
||||
vnf_instance,
|
||||
scale_vnf_request,
|
||||
vnf_lcm_op_occ_id)
|
||||
|
||||
self.vnflcm_driver.scale_vnf(
|
||||
context, vnf_info, vnf_instance, scale_vnf_request)
|
||||
|
@ -301,7 +301,7 @@ class VnfLcmOpOccs(model_base.BASE, models.SoftDeleteMixin,
|
||||
"""VNF LCM OP OCCS Fields"""
|
||||
|
||||
__tablename__ = 'vnf_lcm_op_occs'
|
||||
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
||||
id = sa.Column(sa.String(16), primary_key=True)
|
||||
vnf_instance_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('vnf_instances.id'),
|
||||
nullable=False)
|
||||
@ -316,3 +316,17 @@ class VnfLcmOpOccs(model_base.BASE, models.SoftDeleteMixin,
|
||||
resource_changes = sa.Column(sa.JSON(), nullable=True)
|
||||
changed_info = sa.Column(sa.JSON(), nullable=True)
|
||||
error_point = sa.Column(sa.Integer, nullable=False)
|
||||
|
||||
|
||||
class PlacementConstraint(model_base.BASE, models.SoftDeleteMixin,
|
||||
models.TimestampMixin, models_v1.HasId):
|
||||
"""Represents a Vnf Placement Constraint."""
|
||||
|
||||
__tablename__ = 'placement_constraint'
|
||||
vnf_instance_id = sa.Column(sa.String(36),
|
||||
sa.ForeignKey('vnf_instances.id'),
|
||||
nullable=False)
|
||||
affinity_or_anti_affinity = sa.Column(sa.String(255), nullable=False)
|
||||
scope = sa.Column(sa.String(255), nullable=False)
|
||||
server_group_name = sa.Column(sa.String(255), nullable=False)
|
||||
resource = sa.Column(sa.JSON(), nullable=True)
|
||||
|
@ -0,0 +1,52 @@
|
||||
# Copyright 2020 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""add placement table
|
||||
|
||||
Revision ID: 2c5211036579
|
||||
Revises: ee98bbc0789d
|
||||
Create Date: 2020-09-11 20:47:46.345771
|
||||
|
||||
"""
|
||||
# flake8: noqa: E402
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '2c5211036579'
|
||||
down_revision = 'ee98bbc0789d'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import Boolean
|
||||
|
||||
from tacker.db import types
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
op.create_table(
|
||||
'placement_constraint',
|
||||
sa.Column('id', types.Uuid(length=36), nullable=False),
|
||||
sa.Column('vnf_instance_id', types.Uuid(length=36), nullable=False),
|
||||
sa.Column('affinity_or_anti_affinity',
|
||||
sa.String(length=255), nullable=False),
|
||||
sa.Column('scope', sa.String(length=255), nullable=False),
|
||||
sa.Column('server_group_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('resource', sa.JSON(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('deleted', Boolean, default=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
mysql_engine='InnoDB'
|
||||
)
|
@ -1 +1 @@
|
||||
ee98bbc0789d
|
||||
2c5211036579
|
@ -18,6 +18,7 @@ from datetime import datetime
|
||||
|
||||
from oslo_db.exception import DBDuplicateEntry
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
@ -29,9 +30,11 @@ from sqlalchemy import schema
|
||||
from tacker._i18n import _
|
||||
from tacker.api.v1 import attributes
|
||||
from tacker.common import exceptions
|
||||
import tacker.conf
|
||||
from tacker import context as t_context
|
||||
from tacker.db.common_services import common_services_db_plugin
|
||||
from tacker.db import db_base
|
||||
from tacker.db.db_sqlalchemy import models
|
||||
from tacker.db import model_base
|
||||
from tacker.db import models_v1
|
||||
from tacker.db.nfvo import ns_db
|
||||
@ -40,6 +43,8 @@ from tacker.extensions import vnfm
|
||||
from tacker import manager
|
||||
from tacker.plugins.common import constants
|
||||
|
||||
CONF = tacker.conf.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ACTIVE_UPDATE = (constants.ACTIVE, constants.PENDING_UPDATE,
|
||||
constants.PENDING_HEAL)
|
||||
@ -812,3 +817,51 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
||||
constants.ERROR]
|
||||
return self._mark_vnf_status(
|
||||
vnf_id, exclude_status, constants.DEAD)
|
||||
|
||||
def create_placement_constraint(self, context, placement_obj_list):
|
||||
context.session.add_all(placement_obj_list)
|
||||
|
||||
def get_placement_constraint(self, context, vnf_instance_id):
|
||||
placement_constraint = (
|
||||
self._model_query(context, models.PlacementConstraint).filter(
|
||||
models.PlacementConstraint.vnf_instance_id == vnf_instance_id).
|
||||
filter(models.PlacementConstraint.deleted == 0).all())
|
||||
return placement_constraint
|
||||
|
||||
def update_placement_constraint_heal(self, context,
|
||||
vnf_info,
|
||||
vnf_instance):
|
||||
if not vnf_info.get('grant'):
|
||||
return
|
||||
placement_obj_list = vnf_info['placement_obj_list']
|
||||
inst_info = vnf_instance.instantiated_vnf_info
|
||||
for vnfc in inst_info.vnfc_resource_info:
|
||||
for placement_obj in placement_obj_list:
|
||||
rsc_dict = jsonutils.loads(placement_obj.resource)
|
||||
for rsc in rsc_dict:
|
||||
if vnfc.id == rsc.get('resource_id') and\
|
||||
rsc.get('id_type') == 'GRANT':
|
||||
rsc['id_type'] = 'RES_MGMT'
|
||||
rsc['resource_id'] = vnfc.\
|
||||
compute_resource.resource_id
|
||||
rsc['vim_connection_id'] = vnfc.\
|
||||
compute_resource.vim_connection_id
|
||||
placement_obj.resource = jsonutils.dumps(rsc_dict)
|
||||
self.update_placement_constraint(context, placement_obj)
|
||||
|
||||
def delete_placement_constraint(self, context, vnf_instance_id):
|
||||
(self._model_query(context, models.PlacementConstraint).
|
||||
filter(
|
||||
models.PlacementConstraint.vnf_instance_id == vnf_instance_id).
|
||||
filter(models.PlacementConstraint.deleted == 0).
|
||||
update({'deleted': 0, 'deleted_at': timeutils.utcnow()}))
|
||||
|
||||
def update_placement_constraint(self, context, placement_obj):
|
||||
(self._model_query(
|
||||
context,
|
||||
models.PlacementConstraint).filter(
|
||||
models.PlacementConstraint.id == placement_obj.id).
|
||||
filter(models.PlacementConstraint.deleted == 0).
|
||||
update({
|
||||
'resource': placement_obj.resource,
|
||||
'updated_at': timeutils.utcnow()}))
|
||||
|
@ -42,3 +42,7 @@ def register_all():
|
||||
__import__('tacker.objects.vnf_artifact')
|
||||
__import__('tacker.objects.vnf_lcm_subscriptions')
|
||||
__import__('tacker.objects.scale_vnf_request')
|
||||
__import__('tacker.objects.grant')
|
||||
__import__('tacker.objects.grant_request')
|
||||
__import__('tacker.objects.vnfd')
|
||||
__import__('tacker.objects.vnfd_attribute')
|
||||
|
287
tacker/objects/grant.py
Normal file
287
tacker/objects/grant.py
Normal file
@ -0,0 +1,287 @@
|
||||
# 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 tacker import objects
|
||||
from tacker.objects import base
|
||||
from tacker.objects import fields
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class Grant(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'id': fields.StringField(nullable=False),
|
||||
'vnf_instance_id': fields.StringField(nullable=False),
|
||||
'vnf_lcm_op_occ_id': fields.StringField(nullable=False),
|
||||
'vim_connections': fields.ListOfObjectsField(
|
||||
'VimConnectionInfo', nullable=True, default=[]),
|
||||
'zones': fields.ListOfObjectsField(
|
||||
'ZoneInfo', nullable=True, default=[]),
|
||||
'add_resources': fields.ListOfObjectsField(
|
||||
'GrantInfo', nullable=True, default=[]),
|
||||
'remove_resources': fields.ListOfObjectsField(
|
||||
'GrantInfo', nullable=True, default=[]),
|
||||
'vim_assets': fields.ObjectField(
|
||||
'VimAssets', nullable=True)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_grant = super(
|
||||
Grant, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
if 'vim_connections' in primitive.keys():
|
||||
obj_data = [objects.VimConnectionInfo._from_dict(
|
||||
vim_conn) for vim_conn in primitive.get(
|
||||
'vim_connections', [])]
|
||||
primitive.update({'vim_connections': obj_data})
|
||||
|
||||
if 'zones' in primitive.keys():
|
||||
obj_data = [ZoneInfo._from_dict(
|
||||
zone) for zone in primitive.get(
|
||||
'zones', [])]
|
||||
primitive.update({'zones': obj_data})
|
||||
|
||||
if 'add_resources' in primitive.keys():
|
||||
obj_data = [GrantInfo._from_dict(
|
||||
add_rsc) for add_rsc in primitive.get(
|
||||
'add_resources', [])]
|
||||
primitive.update({'add_resources': obj_data})
|
||||
if 'remove_resources' in primitive.keys():
|
||||
obj_data = [GrantInfo._from_dict(
|
||||
remove_rsc) for remove_rsc in primitive.get(
|
||||
'remove_resources', [])]
|
||||
primitive.update({'remove_resources': obj_data})
|
||||
if 'vim_assets' in primitive.keys():
|
||||
obj_data = VimAssets.obj_from_primitive(
|
||||
primitive.get('vim_assets'), context)
|
||||
primitive.update({'vim_assets': obj_data})
|
||||
|
||||
obj_grant = Grant._from_dict(primitive)
|
||||
|
||||
return obj_grant
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
id = data_dict.get('id')
|
||||
vnf_instance_id = data_dict.get('vnf_instance_id')
|
||||
vnf_lcm_op_occ_id = data_dict.get('vnf_lcm_op_occ_id')
|
||||
vim_connections = data_dict.get('vim_connections', [])
|
||||
zones = data_dict.get('zones', [])
|
||||
add_resources = data_dict.get('add_resources', [])
|
||||
remove_resources = data_dict.get('remove_resources', [])
|
||||
vim_assets = data_dict.get('vim_assets')
|
||||
|
||||
obj = cls(
|
||||
id=id,
|
||||
vnf_instance_id=vnf_instance_id,
|
||||
vnf_lcm_op_occ_id=vnf_lcm_op_occ_id,
|
||||
vim_connections=vim_connections,
|
||||
zones=zones,
|
||||
add_resources=add_resources,
|
||||
remove_resources=remove_resources,
|
||||
vim_assets=vim_assets)
|
||||
return obj
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class ZoneInfo(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'id': fields.StringField(nullable=False),
|
||||
'zone_id': fields.StringField(nullable=False),
|
||||
'vim_connection_id': fields.StringField(nullable=True)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_zone_info = super(
|
||||
ZoneInfo, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
obj_zone_info = ZoneInfo._from_dict(primitive)
|
||||
|
||||
return obj_zone_info
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
id = data_dict.get('id')
|
||||
zone_id = data_dict.get('zone_id')
|
||||
vim_connection_id = data_dict.get('vim_connection_id')
|
||||
|
||||
obj = cls(
|
||||
id=id,
|
||||
zone_id=zone_id,
|
||||
vim_connection_id=vim_connection_id)
|
||||
return obj
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class GrantInfo(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'resource_definition_id': fields.StringField(nullable=False),
|
||||
'vim_connection_id': fields.StringField(nullable=True),
|
||||
'zone_id': fields.StringField(nullable=True)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_grant_info = super(
|
||||
GrantInfo, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
obj_grant_info = GrantInfo._from_dict(primitive)
|
||||
|
||||
return obj_grant_info
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
resource_definition_id = data_dict.get('resource_definition_id')
|
||||
vim_connection_id = data_dict.get('vim_connection_id')
|
||||
zone_id = data_dict.get('zone_id')
|
||||
|
||||
obj = cls(
|
||||
resource_definition_id=resource_definition_id,
|
||||
vim_connection_id=vim_connection_id,
|
||||
zone_id=zone_id)
|
||||
return obj
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class VimAssets(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'compute_resource_flavours': fields.ListOfObjectsField(
|
||||
'VimComputeResourceFlavour', nullable=True, default=[]),
|
||||
'software_images': fields.ListOfObjectsField(
|
||||
'VimSoftwareImage', nullable=True, default=[])
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_vim_assets = super(
|
||||
VimAssets, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
if 'compute_resource_flavours' in primitive.keys():
|
||||
obj_data = [VimComputeResourceFlavour._from_dict(
|
||||
flavour) for flavour in primitive.get(
|
||||
'compute_resource_flavours', [])]
|
||||
primitive.update({'compute_resource_flavours': obj_data})
|
||||
|
||||
if 'software_images' in primitive.keys():
|
||||
obj_data = [VimSoftwareImage._from_dict(
|
||||
img) for img in primitive.get(
|
||||
'software_images', [])]
|
||||
primitive.update({'software_images': obj_data})
|
||||
obj_vim_assets = VimAssets._from_dict(primitive)
|
||||
|
||||
return obj_vim_assets
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
compute_resource_flavours = data_dict.get(
|
||||
'compute_resource_flavours', [])
|
||||
software_images = data_dict.get('software_images', [])
|
||||
|
||||
obj = cls(
|
||||
compute_resource_flavours=compute_resource_flavours,
|
||||
software_images=software_images)
|
||||
return obj
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class VimComputeResourceFlavour(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'vim_connection_id': fields.StringField(nullable=True),
|
||||
'vnfd_virtual_compute_desc_id': fields.StringField(nullable=False),
|
||||
'vim_flavour_id': fields.StringField(nullable=False)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_flavour = super(
|
||||
VimComputeResourceFlavour,
|
||||
cls).obj_from_primitive(
|
||||
primitive,
|
||||
context)
|
||||
else:
|
||||
obj_flavour = VimComputeResourceFlavour._from_dict(primitive)
|
||||
|
||||
return obj_flavour
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
vim_connection_id = data_dict.get('vim_connection_id')
|
||||
vnfd_virtual_compute_desc_id = data_dict.get(
|
||||
'vnfd_virtual_compute_desc_id')
|
||||
vim_flavour_id = data_dict.get('vim_flavour_id')
|
||||
|
||||
obj = cls(
|
||||
vim_connection_id=vim_connection_id,
|
||||
vnfd_virtual_compute_desc_id=vnfd_virtual_compute_desc_id,
|
||||
vim_flavour_id=vim_flavour_id)
|
||||
return obj
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class VimSoftwareImage(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'vim_connection_id': fields.StringField(nullable=True),
|
||||
'vnfd_software_image_id': fields.StringField(nullable=False),
|
||||
'vim_software_image_id': fields.StringField(nullable=False)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_img = super(
|
||||
VimSoftwareImage, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
obj_img = VimSoftwareImage._from_dict(primitive)
|
||||
|
||||
return obj_img
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
vim_connection_id = data_dict.get('vim_connection_id')
|
||||
vnfd_software_image_id = data_dict.get('vnfd_software_image_id')
|
||||
vim_software_image_id = data_dict.get('vim_software_image_id')
|
||||
|
||||
obj = cls(
|
||||
vim_connection_id=vim_connection_id,
|
||||
vnfd_software_image_id=vnfd_software_image_id,
|
||||
vim_software_image_id=vim_software_image_id)
|
||||
return obj
|
407
tacker/objects/grant_request.py
Normal file
407
tacker/objects/grant_request.py
Normal file
@ -0,0 +1,407 @@
|
||||
# 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 oslo_serialization import jsonutils
|
||||
|
||||
from tacker.common import utils
|
||||
from tacker.objects import base
|
||||
from tacker.objects import fields
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class GrantRequest(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'vnf_instance_id': fields.StringField(nullable=False),
|
||||
'vnf_lcm_op_occ_id': fields.StringField(nullable=False),
|
||||
'vnfd_id': fields.StringField(nullable=False),
|
||||
'flavour_id': fields.StringField(nullable=True),
|
||||
'operation': fields.StringField(nullable=False),
|
||||
'is_automatic_invocation': fields.BooleanField(nullable=False,
|
||||
default=False),
|
||||
'add_resources': fields.ListOfObjectsField(
|
||||
'ResourceDefinition', nullable=True, default=[]),
|
||||
'remove_resources': fields.ListOfObjectsField(
|
||||
'ResourceDefinition', nullable=True, default=[]),
|
||||
'placement_constraints': fields.ListOfObjectsField(
|
||||
'PlacementConstraint', nullable=True, default=[]),
|
||||
'_links': fields.ObjectField(
|
||||
'Links', nullable=False)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_grant_req = super(
|
||||
GrantRequest, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
if 'add_resources' in primitive.keys():
|
||||
obj_data = [ResourceDefinition._from_dict(
|
||||
add_rsc) for add_rsc in primitive.get(
|
||||
'add_resources', [])]
|
||||
primitive.update({'add_resources': obj_data})
|
||||
if 'remove_resources' in primitive.keys():
|
||||
obj_data = [ResourceDefinition._from_dict(
|
||||
remove_rsc) for remove_rsc in primitive.get(
|
||||
'remove_resources', [])]
|
||||
primitive.update({'add_resources': obj_data})
|
||||
if 'placement_constraints' in primitive.keys():
|
||||
obj_data = [PlacementConstraint._from_dict(
|
||||
place) for place in primitive.get(
|
||||
'placement_constraints', [])]
|
||||
primitive.update({'add_resources': obj_data})
|
||||
obj_grant_req = GrantRequest._from_dict(primitive)
|
||||
|
||||
return obj_grant_req
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
vnf_instance_id = data_dict.get('vnf_instance_id')
|
||||
vnf_lcm_op_occ_id = data_dict.get('vnf_lcm_op_occ_id')
|
||||
vnfd_id = data_dict.get('vnfd_id')
|
||||
flavour_id = data_dict.get('flavour_id')
|
||||
operation = data_dict.get('operation')
|
||||
is_automatic_invocation = data_dict.get('is_automatic_invocation')
|
||||
add_resources = data_dict.get('add_resources', [])
|
||||
remove_resources = data_dict.get('remove_resources', [])
|
||||
placement_constraints = data_dict.get('placement_constraints', [])
|
||||
links = data_dict.get('_links')
|
||||
|
||||
obj = cls(
|
||||
vnf_instance_id=vnf_instance_id,
|
||||
vnf_lcm_op_occ_id=vnf_lcm_op_occ_id,
|
||||
vnfd_id=vnfd_id,
|
||||
flavour_id=flavour_id,
|
||||
operation=operation,
|
||||
is_automatic_invocation=is_automatic_invocation,
|
||||
add_resources=add_resources,
|
||||
remove_resources=remove_resources,
|
||||
placement_constraints=placement_constraints,
|
||||
_links=links)
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
data = {'vnf_instance_id': self.vnf_instance_id,
|
||||
'vnf_lcm_op_occ_id': self.vnf_lcm_op_occ_id,
|
||||
'vnfd_id': self.vnfd_id,
|
||||
'flavour_id': self.flavour_id,
|
||||
'operation': self.operation,
|
||||
'is_automatic_invocation': self.is_automatic_invocation,
|
||||
'_links': self._links.to_dict()}
|
||||
if self.add_resources:
|
||||
add_resources_list = []
|
||||
for add_resource in self.add_resources:
|
||||
add_resources_list.append(add_resource.to_dict())
|
||||
|
||||
data.update({'add_resources': add_resources_list})
|
||||
if self.remove_resources:
|
||||
remove_resources_list = []
|
||||
for remove_resource in self.remove_resources:
|
||||
remove_resources_list.append(remove_resource.to_dict())
|
||||
|
||||
data.update({'remove_resources': remove_resources_list})
|
||||
if self.placement_constraints:
|
||||
placement_constraints_list = []
|
||||
for placement_constraint in self.placement_constraints:
|
||||
placement_constraints_list.append(
|
||||
placement_constraint.to_dict())
|
||||
|
||||
data.update({'placement_constraints': placement_constraints_list})
|
||||
return data
|
||||
|
||||
def to_request_body(self):
|
||||
req_dict = self.to_dict()
|
||||
req_dict = utils.convert_snakecase_to_camelcase(req_dict)
|
||||
return jsonutils.dumps(req_dict).replace('Links', '_links')
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class ResourceDefinition(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'id': fields.StringField(nullable=False),
|
||||
'type': fields.StringField(nullable=False),
|
||||
'vdu_id': fields.StringField(nullable=True, default=None),
|
||||
'resource_template_id': fields.StringField(nullable=False),
|
||||
'resource': fields.ObjectField(
|
||||
'ResourceHandle', nullable=True, default=None)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_grant_req = super(
|
||||
ResourceDefinition, cls).\
|
||||
obj_from_primitive(primitive, context)
|
||||
else:
|
||||
if 'resource' in primitive.keys():
|
||||
obj_data = ResourceHandle._from_dict(
|
||||
primitive.get('resource'))
|
||||
primitive.update({'resource': obj_data})
|
||||
obj_grant_req = ResourceDefinition._from_dict(primitive)
|
||||
|
||||
return obj_grant_req
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
id = data_dict.get('id')
|
||||
type = data_dict.get('type')
|
||||
vdu_id = data_dict.get('vdu_id')
|
||||
resource_template_id = data_dict.get('resource_template_id')
|
||||
resource = data_dict.get('resource')
|
||||
|
||||
obj = cls(
|
||||
id=id,
|
||||
type=type,
|
||||
vdu_id=vdu_id,
|
||||
resource_template_id=resource_template_id,
|
||||
resource=resource)
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
data = {'id': self.id,
|
||||
'type': self.type,
|
||||
'resource_template_id': self.resource_template_id}
|
||||
if self.vdu_id:
|
||||
data.update({'vdu_id': self.vdu_id})
|
||||
if self.resource:
|
||||
data.update({'resource': self.resource.to_dict()})
|
||||
return data
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class PlacementConstraint(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'affinity_or_anti_affinity': fields.StringField(nullable=False),
|
||||
'scope': fields.StringField(nullable=False),
|
||||
'resource': fields.ListOfObjectsField(
|
||||
'ConstraintResourceRef', nullable=False, default=[]),
|
||||
'fallback_best_effort': fields.BooleanField(nullable=False),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_placement_constraint = super(
|
||||
PlacementConstraint, cls).obj_from_primitive(
|
||||
primitive, context)
|
||||
else:
|
||||
if 'resource' in primitive.keys():
|
||||
obj_data = [ConstraintResourceRef._from_dict(
|
||||
add_rsc) for add_rsc in primitive.get(
|
||||
'resource', [])]
|
||||
primitive.update({'resource': obj_data})
|
||||
obj_placement_constraint = PlacementConstraint._from_dict(
|
||||
primitive)
|
||||
|
||||
return obj_placement_constraint
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
affinity_or_anti_affinity = data_dict.get('affinity_or_anti_affinity')
|
||||
scope = data_dict.get('scope')
|
||||
resource = data_dict.get('resource')
|
||||
fallback_best_effort = data_dict.get('fallback_best_effort')
|
||||
|
||||
obj = cls(
|
||||
affinity_or_anti_affinity=affinity_or_anti_affinity,
|
||||
scope=scope,
|
||||
resource=resource,
|
||||
fallback_best_effort=fallback_best_effort)
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
data = {'affinity_or_anti_affinity': self.affinity_or_anti_affinity,
|
||||
'scope': self.scope,
|
||||
'fallback_best_effort': self.fallback_best_effort}
|
||||
if self.resource:
|
||||
resource_list = []
|
||||
for rsc in self.resource:
|
||||
resource_list.append(rsc.to_dict())
|
||||
|
||||
data.update({'resource': resource_list})
|
||||
return data
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class ConstraintResourceRef(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'id_type': fields.StringField(nullable=False),
|
||||
'resource_id': fields.StringField(nullable=False),
|
||||
'vim_connection_id': fields.StringField(nullable=True, default=None),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_placement_constraint = super(
|
||||
ConstraintResourceRef, cls).obj_from_primitive(
|
||||
primitive, context)
|
||||
else:
|
||||
obj_placement_constraint = ConstraintResourceRef._from_dict(
|
||||
primitive)
|
||||
|
||||
return obj_placement_constraint
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
id_type = data_dict.get('id_type')
|
||||
resource_id = data_dict.get('resource_id')
|
||||
vim_connection_id = data_dict.get('vim_connection_id')
|
||||
|
||||
obj = cls(
|
||||
id_type=id_type,
|
||||
resource_id=resource_id,
|
||||
vim_connection_id=vim_connection_id)
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
data = {'id_type': self.id_type,
|
||||
'resource_id': self.resource_id}
|
||||
if self.vim_connection_id:
|
||||
data.update({'vim_connection_id': self.vim_connection_id})
|
||||
return data
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class Links(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'vnf_lcm_op_occ': fields.ObjectField(
|
||||
'Link', nullable=False),
|
||||
'vnf_instance': fields.ObjectField(
|
||||
'Link', nullable=False)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_links = super(
|
||||
Links, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
if 'vnf_lcm_op_occ' in primitive.keys():
|
||||
obj_data = Link._from_dict(
|
||||
primitive.get('vnf_lcm_op_occ'))
|
||||
primitive.update({'vnf_lcm_op_occ': obj_data})
|
||||
if 'vnf_instance' in primitive.keys():
|
||||
obj_data = Link._from_dict(
|
||||
primitive.get('vnf_instance'))
|
||||
primitive.update({'vnf_instance': obj_data})
|
||||
obj_links = Links._from_dict(primitive)
|
||||
|
||||
return obj_links
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
vnf_lcm_op_occ = data_dict.get('vnf_lcm_op_occ')
|
||||
vnf_instance = data_dict.get('vnf_instance')
|
||||
|
||||
obj = cls(
|
||||
vnf_lcm_op_occ=vnf_lcm_op_occ,
|
||||
vnf_instance=vnf_instance)
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
return {'vnf_lcm_op_occ': self.vnf_lcm_op_occ.to_dict(),
|
||||
'vnf_instance': self.vnf_instance.to_dict()}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class Link(base.TackerObject):
|
||||
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'href': fields.StringField(nullable=False)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
obj_link = super(
|
||||
Link, cls).obj_from_primitive(primitive, context)
|
||||
else:
|
||||
obj_link = Link._from_dict(primitive)
|
||||
|
||||
return obj_link
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
href = data_dict.get('href')
|
||||
|
||||
obj = cls(
|
||||
href=href)
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
return {'href': self.href}
|
||||
|
||||
|
||||
@base.TackerObjectRegistry.register
|
||||
class ResourceHandle(base.TackerObject,
|
||||
base.TackerPersistentObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'vim_connection_id': fields.StringField(nullable=True,
|
||||
default=None),
|
||||
'resource_id': fields.StringField(nullable=False, default=""),
|
||||
'vim_level_resource_type': fields.StringField(nullable=True,
|
||||
default=None)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_primitive(cls, primitive, context):
|
||||
if 'tacker_object.name' in primitive:
|
||||
resource_handle = super(
|
||||
ResourceHandle, cls).obj_from_primitive(
|
||||
primitive, context)
|
||||
else:
|
||||
resource_handle = ResourceHandle._from_dict(primitive)
|
||||
|
||||
return resource_handle
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
vim_connection_id = data_dict.get('vim_connection_id')
|
||||
resource_id = data_dict.get('resource_id', "")
|
||||
vim_level_resource_type = data_dict.get('vim_level_resource_type')
|
||||
|
||||
obj = cls(vim_connection_id=vim_connection_id,
|
||||
resource_id=resource_id,
|
||||
vim_level_resource_type=vim_level_resource_type)
|
||||
|
||||
return obj
|
||||
|
||||
def to_dict(self):
|
||||
return {'vim_connection_id': self.vim_connection_id,
|
||||
'resource_id': self.resource_id,
|
||||
'vim_level_resource_type': self.vim_level_resource_type}
|
@ -32,14 +32,14 @@ COMMON_PREFIXES = {
|
||||
ACTIVE = "ACTIVE"
|
||||
ACK = "ACK"
|
||||
INACTIVE = "INACTIVE"
|
||||
|
||||
PENDING_INSTANTIATE = "PENDING_INSTANTIATE"
|
||||
PENDING_CREATE = "PENDING_CREATE"
|
||||
PENDING_UPDATE = "PENDING_UPDATE"
|
||||
PENDING_DELETE = "PENDING_DELETE"
|
||||
PENDING_SCALE_IN = "PENDING_SCALE_IN"
|
||||
PENDING_SCALE_OUT = "PENDING_SCALE_OUT"
|
||||
PENDING_HEAL = "PENDING_HEAL"
|
||||
|
||||
PENDING_TERMINATE = "PENDING_TERMINATE"
|
||||
DEAD = "DEAD"
|
||||
ERROR = "ERROR"
|
||||
NACK = "NACK"
|
||||
@ -55,6 +55,7 @@ POLICY_SCALING_ACTIONS = (ACTION_SCALE_OUT,
|
||||
ACTION_SCALE_IN) = ('out', 'in')
|
||||
POLICY_ACTIONS = {POLICY_SCALING: POLICY_SCALING_ACTIONS}
|
||||
POLICY_ALARMING = 'tosca.policies.tacker.Alarming'
|
||||
POLICY_EVENT_ALARMING = 'tosca.policies.tacker.EventAlarming'
|
||||
VALID_POLICY_TYPES = [POLICY_SCALING, POLICY_ALARMING]
|
||||
POLICY_RESERVATION = 'tosca.policies.tacker.Reservation'
|
||||
RESERVATION_POLICY_ACTIONS = ['start_actions',
|
||||
@ -68,6 +69,8 @@ RES_TYPE_VNF = "vnf"
|
||||
RES_TYPE_VIM = "vim"
|
||||
|
||||
RES_EVT_CREATE = "CREATE"
|
||||
RES_EVT_INSTANTIATE = "INSTANTIATE"
|
||||
RES_EVT_TERMINATE = "TERMINATE"
|
||||
RES_EVT_DELETE = "DELETE"
|
||||
RES_EVT_UPDATE = "UPDATE"
|
||||
RES_EVT_MONITOR = "MONITOR"
|
||||
@ -90,3 +93,8 @@ VNF_STATUS_TO_EVT_TYPES = {PENDING_CREATE: RES_EVT_CREATE,
|
||||
RES_EVT_CREATED_FLD = "created_at"
|
||||
RES_EVT_DELETED_FLD = "deleted_at"
|
||||
RES_EVT_UPDATED_FLD = "updated_at"
|
||||
|
||||
TYPE_COMPUTE = "COMPUTE"
|
||||
TYPE_LINKPORT = "LINKPORT"
|
||||
TYPE_STORAGE = "STORAGE"
|
||||
TYPE_VL = "VL"
|
||||
|
0
tacker/tests/contrib/post_test_hook.sh
Executable file → Normal file
0
tacker/tests/contrib/post_test_hook.sh
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/common/Files/images/cirros-0.4.0-x86_64-disk.img
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/common/Files/images/cirros-0.4.0-x86_64-disk.img
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/Definitions/helloworld3_df_simple.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/Definitions/helloworld3_df_simple.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/Definitions/helloworld3_top.vnfd.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/Definitions/helloworld3_top.vnfd.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/Definitions/helloworld3_types.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/Definitions/helloworld3_types.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/TOSCA-Metadata/TOSCA.meta
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm1/TOSCA-Metadata/TOSCA.meta
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/Definitions/helloworld3_df_simple.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/Definitions/helloworld3_df_simple.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/Definitions/helloworld3_top.vnfd.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/Definitions/helloworld3_top.vnfd.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/Definitions/helloworld3_types.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/Definitions/helloworld3_types.yaml
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/TOSCA-Metadata/TOSCA.meta
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm2/TOSCA-Metadata/TOSCA.meta
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm4/TOSCA-Metadata/TOSCA.meta
Executable file → Normal file
0
tacker/tests/etc/samples/etsi/nfv/vnflcm4/TOSCA-Metadata/TOSCA.meta
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,7 @@ tosca_cvnf_vnfd = _get_template('test_tosca_cvnf.yaml')
|
||||
tosca_vnfd_openwrt = _get_template('test_tosca_openwrt.yaml')
|
||||
tosca_vnfd_openwrt_param = _get_template('test_tosca_openwrt_param.yaml')
|
||||
tosca_invalid_vnfd = _get_template('test_tosca_parser_failure.yaml')
|
||||
etsi_vnfd = _get_template('etsi_nfv/tosca_vnfd.yaml')
|
||||
config_data = _get_template('config_data.yaml')
|
||||
update_config_data = _get_template('update_config_data.yaml')
|
||||
hot_data = _get_template('hot_data.yaml')
|
||||
@ -74,6 +75,11 @@ vnffgd_wrong_cp_number_template = yaml.safe_load(_get_template(
|
||||
'tosca_vnffgd_wrong_cp_number_template.yaml'))
|
||||
vnfd_instance_reservation_alarm_scale_tosca_template = _get_template(
|
||||
'test_tosca-vnfd-instance-reservation.yaml')
|
||||
hot_grant = _get_template('hot_grant.yaml')
|
||||
hot_scale_grant = _get_template('hot_scale_grant.yaml')
|
||||
hot_scale_nest_grant = _get_template('hot_scale_nest_grant.yaml')
|
||||
hot_scale_initial = _get_template('hot_scale_initial.yaml')
|
||||
hot_scale_nest_initial = _get_template('hot_scale_nest_initial.yaml')
|
||||
|
||||
|
||||
def get_dummy_vnfd_obj():
|
||||
@ -190,6 +196,57 @@ def get_dummy_vnf(status='PENDING_CREATE', scaling_group=False,
|
||||
return dummy_vnf
|
||||
|
||||
|
||||
def get_dummy_vnf_test(status='PENDING_CREATE', scaling_group=False,
|
||||
instance_id=None):
|
||||
dummy_vnf = {'status': status, 'instance_id': instance_id, 'name':
|
||||
u'test_openwrt', 'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'vnfd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'vnfd': {
|
||||
'service_types': [{'service_type': u'vnfd',
|
||||
'id': u'4a4c2d44-8a52-4895-9a75-9d1c76c3e738'}],
|
||||
'description': u'OpenWRT with services',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'mgmt_driver': u'openwrt',
|
||||
'attributes': {u'vnfd_simple': tosca_vnfd_openwrt},
|
||||
'id': u'fb048660-dc1b-4f0f-bd89-b023666650ec',
|
||||
'name': u'openwrt_services'},
|
||||
'mgmt_ip_address': None, 'service_context': [],
|
||||
'attributes': {u'param_values': u''},
|
||||
'id': 'eb84260e-5ff7-4332-b032-50a14d6c1123',
|
||||
'description': u'OpenWRT with services'}
|
||||
if scaling_group:
|
||||
dummy_vnf['attributes'].update({'scaling_group_names':
|
||||
'{"SP1": "SP1_group"}',
|
||||
'heat_template': 'test'})
|
||||
return dummy_vnf
|
||||
|
||||
|
||||
def get_dummy_vnf_etsi(status='PENDING_CREATE', scaling_group=False,
|
||||
instance_id=None, flavour='Simple'):
|
||||
vnfd_key = 'vnfd_' + flavour
|
||||
dummy_vnf = {'status': status, 'instance_id': instance_id, 'name':
|
||||
u'test_openwrt', 'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'vnfd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'vnfd': {
|
||||
'service_types': [{'service_type': u'vnfd',
|
||||
'id': u'4a4c2d44-8a52-4895-9a75-9d1c76c3e738'}],
|
||||
'description': u'OpenWRT with services',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'mgmt_driver': u'openwrt',
|
||||
'attributes': {vnfd_key: etsi_vnfd},
|
||||
'id': u'fb048660-dc1b-4f0f-bd89-b023666650ec',
|
||||
'name': u'openwrt_services'},
|
||||
'mgmt_ip_address': None, 'service_context': [],
|
||||
'attributes': {u'param_values': u''},
|
||||
'id': 'eb84260e-5ff7-4332-b032-50a14d6c1123',
|
||||
'description': u'OpenWRT with services'}
|
||||
if scaling_group:
|
||||
dummy_vnf['attributes'].update({'scaling_group_names':
|
||||
'{"SP1": "SP1_group"}',
|
||||
'heat_template': 'test'})
|
||||
return dummy_vnf
|
||||
|
||||
|
||||
def get_dummy_vnf_config_attr():
|
||||
return {'status': 'PENDING_CREATE', 'instance_id': None, 'name':
|
||||
u'test_openwrt', 'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
@ -483,3 +540,23 @@ def get_dummy_vim_connection_info():
|
||||
'created_at': '', 'deleted': False, 'deleted_at': '',
|
||||
'id': 'fake_id', 'updated_at': '',
|
||||
'vim_id': 'fake_vim_id', 'vim_type': 'openstack'}
|
||||
|
||||
|
||||
def get_dummy_grant_hot():
|
||||
return str(hot_grant)
|
||||
|
||||
|
||||
def get_dummy_scale_grant_hot():
|
||||
return str(hot_scale_grant)
|
||||
|
||||
|
||||
def get_dummy_scale_nest_grant_hot():
|
||||
return str(hot_scale_nest_grant)
|
||||
|
||||
|
||||
def get_dummy_scale_initial_hot():
|
||||
return str(hot_scale_initial)
|
||||
|
||||
|
||||
def get_dummy_scale_nest_initial_hot():
|
||||
return str(hot_scale_nest_initial)
|
||||
|
@ -245,8 +245,9 @@ def get_vnf_instance_data_with_id(vnfd_id):
|
||||
}
|
||||
|
||||
|
||||
def get_lcm_op_occs_data(vnf_instance_id):
|
||||
def get_lcm_op_occs_data(id, vnf_instance_id):
|
||||
return {
|
||||
"id": id,
|
||||
"tenant_id": uuidsentinel.tenant_id,
|
||||
'operation_state': 'PROCESSING',
|
||||
'state_entered_time': datetime.datetime(1900, 1, 1, 1, 1, 1,
|
||||
|
@ -16,6 +16,8 @@
|
||||
import ddt
|
||||
from unittest import mock
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.common import exceptions
|
||||
from tacker import context
|
||||
from tacker.db import api as sqlalchemy_api
|
||||
@ -231,7 +233,9 @@ class TestVnfInstance(SqlTestCase):
|
||||
vnf_instance = objects.VnfInstance(context=self.context,
|
||||
**vnf_instance_data)
|
||||
vnf_instance.create()
|
||||
id = uuidutils.generate_uuid()
|
||||
vnf_lcm_oppccs = fakes.get_lcm_op_occs_data(
|
||||
id,
|
||||
vnf_instance.id)
|
||||
|
||||
vnf_instance.update(
|
||||
|
@ -11,6 +11,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker import context
|
||||
from tacker import objects
|
||||
from tacker.tests.unit.db.base import SqlTestCase
|
||||
@ -58,21 +60,27 @@ class TestVnfLcmOpOcc(SqlTestCase):
|
||||
return vnf_instance
|
||||
|
||||
def _create_vnf_lcm_op_occs(self):
|
||||
vnf_lcm_op_occs_data = fakes.get_lcm_op_occs_data(self.vnf_instance.id)
|
||||
id = uuidutils.generate_uuid()
|
||||
vnf_lcm_op_occs_data = \
|
||||
fakes.get_lcm_op_occs_data(id, self.vnf_instance.id)
|
||||
vnf_lcm_op_occs = objects.vnf_lcm_op_occs.VnfLcmOpOcc(
|
||||
context=self.context, **vnf_lcm_op_occs_data)
|
||||
vnf_lcm_op_occs.create()
|
||||
return vnf_lcm_op_occs
|
||||
|
||||
def test_create(self):
|
||||
vnf_lcm_op_occs_data = fakes.get_lcm_op_occs_data(self.vnf_instance.id)
|
||||
id = uuidutils.generate_uuid()
|
||||
vnf_lcm_op_occs_data = \
|
||||
fakes.get_lcm_op_occs_data(id, self.vnf_instance.id)
|
||||
vnf_lcm_op_occs = objects.vnf_lcm_op_occs.VnfLcmOpOcc(
|
||||
context=self.context, **vnf_lcm_op_occs_data)
|
||||
vnf_lcm_op_occs.create()
|
||||
self.assertTrue(vnf_lcm_op_occs.vnf_instance_id)
|
||||
|
||||
def test_save(self):
|
||||
vnf_lcm_op_occs_data = fakes.get_lcm_op_occs_data(self.vnf_instance.id)
|
||||
id = uuidutils.generate_uuid()
|
||||
vnf_lcm_op_occs_data = \
|
||||
fakes.get_lcm_op_occs_data(id, self.vnf_instance.id)
|
||||
vnf_lcm_op_occs = objects.vnf_lcm_op_occs.VnfLcmOpOcc(
|
||||
context=self.context, **vnf_lcm_op_occs_data)
|
||||
vnf_lcm_op_occs.create()
|
||||
|
@ -473,6 +473,10 @@ def get_instantiate_vnf_request_obj():
|
||||
ext_managed_virtual_link_data = ExtManagedVirtualLinkData()
|
||||
vim_connection_info = VimConnectionInfo()
|
||||
ext_virtual_link_data = ExtVirtualLinkData()
|
||||
ext_managed_virtual_link_data.id = uuidsentinel.ext_id
|
||||
ext_managed_virtual_link_data.vnf_virtual_link_desc_id = 'VL3'
|
||||
ext_managed_virtual_link_data.resource_id = \
|
||||
'f8c35bd0-4d67-4436-9f11-14b8a84c92aa'
|
||||
instantiate_vnf_req.additional_params = None
|
||||
instantiate_vnf_req.deleted = 0
|
||||
instantiate_vnf_req.ext_managed_virtual_links = \
|
||||
|
@ -113,6 +113,10 @@ class FakeDriverManager(mock.Mock):
|
||||
if self.fail_method_name and \
|
||||
self.fail_method_name == 'heal_vnf':
|
||||
raise InfraDriverException("heal_vnf failed")
|
||||
elif 'heal_vnf_standard' in args:
|
||||
if self.fail_method_name and \
|
||||
self.fail_method_name == 'heal_vnf_standard':
|
||||
raise InfraDriverException("heal_vnf_standard failed")
|
||||
elif 'heal_vnf_wait' in args:
|
||||
if self.fail_method_name and \
|
||||
self.fail_method_name == 'heal_vnf_wait':
|
||||
@ -196,10 +200,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
driver.instantiate_vnf(self.context, vnf_instance_obj, vnf_dict,
|
||||
instantiate_vnf_req_obj)
|
||||
|
||||
self.assertEqual("INSTANTIATED", vnf_instance_obj.instantiation_state)
|
||||
self.assertEqual(2, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(4, self._vnf_manager.invoke.call_count)
|
||||
mock_final_vnf_dict.assert_called_once()
|
||||
self.assertEqual(1, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(3, self._vnf_manager.invoke.call_count)
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@ -232,10 +234,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
driver.instantiate_vnf(self.context, vnf_instance_obj, vnf_dict,
|
||||
instantiate_vnf_req_obj)
|
||||
|
||||
self.assertEqual("INSTANTIATED", vnf_instance_obj.instantiation_state)
|
||||
self.assertEqual(2, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(4, self._vnf_manager.invoke.call_count)
|
||||
mock_final_vnf_dict.assert_called_once()
|
||||
self.assertEqual(1, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(3, self._vnf_manager.invoke.call_count)
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@ -268,10 +268,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
driver.instantiate_vnf(self.context, vnf_instance_obj, vnf_dict,
|
||||
instantiate_vnf_req_obj)
|
||||
|
||||
self.assertEqual("INSTANTIATED", vnf_instance_obj.instantiation_state)
|
||||
self.assertEqual(2, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(4, self._vnf_manager.invoke.call_count)
|
||||
mock_final_vnf_dict.assert_called_once()
|
||||
self.assertEqual(1, mock_vnf_instance_save.call_count)
|
||||
self.assertEqual(3, self._vnf_manager.invoke.call_count)
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@ -335,6 +333,12 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
objects.InstantiateVnfRequest.obj_from_primitive(
|
||||
instantiate_vnf_req_dict, self.context)
|
||||
vnf_instance_obj = fakes.return_vnf_instance()
|
||||
level = instantiate_vnf_req_obj.instantiation_level_id
|
||||
vnf_instance_obj.instantiated_vnf_info = objects.InstantiatedVnfInfo(
|
||||
flavour_id=instantiate_vnf_req_obj.flavour_id,
|
||||
instantiation_level_id=level,
|
||||
vnf_instance_id=vnf_instance_obj.id,
|
||||
ext_cp_info=[])
|
||||
|
||||
fake_csar = os.path.join(self.temp_dir, vnf_package_id)
|
||||
cfg.CONF.set_override('vnf_package_csar_path', self.temp_dir,
|
||||
@ -386,7 +390,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
driver.instantiate_vnf(self.context, vnf_instance_obj, vnf_dict,
|
||||
instantiate_vnf_req_obj)
|
||||
self.assertEqual(2, mock_create.call_count)
|
||||
self.assertEqual("INSTANTIATED", vnf_instance_obj.instantiation_state)
|
||||
self.assertEqual("NOT_INSTANTIATED",
|
||||
vnf_instance_obj.instantiation_state)
|
||||
mock_final_vnf_dict.assert_called_once()
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@ -419,7 +424,6 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
driver.instantiate_vnf(self.context, vnf_instance_obj, vnf_dict,
|
||||
instantiate_vnf_req_obj)
|
||||
self.assertEqual(2, mock_create.call_count)
|
||||
self.assertEqual("INSTANTIATED", vnf_instance_obj.instantiation_state)
|
||||
mock_final_vnf_dict.assert_called_once()
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@ -540,6 +544,7 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id')
|
||||
@mock.patch.object(vim_client.VimClient, "get_vim")
|
||||
@mock.patch.object(objects.VnfResource, "create")
|
||||
@ -550,7 +555,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
def test_heal_vnf_without_vnfc_instance(self, mock_log, mock_save,
|
||||
mock_vnf_resource_list, mock_resource_destroy,
|
||||
mock_resource_create, mock_vim, mock_vnf_package_vnfd,
|
||||
mock_get_service_plugins, mock_final_vnf_dict):
|
||||
mock_make_final_vnf_dict, mock_get_service_plugins,
|
||||
mock_final_vnf_dict):
|
||||
vnf_package_vnfd = fakes.return_vnf_package_vnfd()
|
||||
vnf_package_id = vnf_package_vnfd.package_uuid
|
||||
mock_vnf_package_vnfd.return_value = vnf_package_vnfd
|
||||
@ -582,6 +588,7 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
vnf_dict = {"attributes": {}}
|
||||
mock_make_final_vnf_dict.return_value = {}
|
||||
driver.heal_vnf(self.context, vnf_instance, vnf_dict, heal_vnf_req)
|
||||
self.assertEqual(1, mock_save.call_count)
|
||||
# vnf resource software images will be deleted during
|
||||
@ -590,9 +597,9 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
# Vnf resource software images will be created during
|
||||
# instantiation.
|
||||
self.assertEqual(1, mock_resource_create.call_count)
|
||||
# Invoke will be called 7 times, 3 for deleting the vnf
|
||||
# resources and 4 during instantiation.
|
||||
self.assertEqual(7, self._vnf_manager.invoke.call_count)
|
||||
# Invoke will be called 6 times, 3 for deleting the vnf
|
||||
# resources and 3 during instantiation.
|
||||
self.assertEqual(6, self._vnf_manager.invoke.call_count)
|
||||
expected_msg = ("Request received for healing vnf '%s' "
|
||||
"is completed successfully")
|
||||
mock_log.info.assert_called_with(expected_msg,
|
||||
@ -632,6 +639,7 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id')
|
||||
@mock.patch.object(vim_client.VimClient, "get_vim")
|
||||
@mock.patch.object(objects.VnfResource, "create")
|
||||
@ -642,8 +650,8 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
def test_heal_vnf_without_vnfc_instance_infra_instantiate_vnf_fail(self,
|
||||
mock_log, mock_save, mock_vnf_resource_list,
|
||||
mock_resource_destroy, mock_resource_create, mock_vim,
|
||||
mock_vnf_package_vnfd, mock_get_service_plugins,
|
||||
mock_final_vnf_dict):
|
||||
mock_vnf_package_vnfd, mock_make_final_vnf_dict,
|
||||
mock_get_service_plugins, mock_final_vnf_dict):
|
||||
vnf_package_vnfd = fakes.return_vnf_package_vnfd()
|
||||
vnf_package_id = vnf_package_vnfd.package_uuid
|
||||
mock_vnf_package_vnfd.return_value = vnf_package_vnfd
|
||||
@ -664,6 +672,7 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
self._mock_vnf_manager(fail_method_name='instantiate_vnf')
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
vnf_dict = {"fake": "fake_dict"}
|
||||
mock_make_final_vnf_dict.return_value = {}
|
||||
self.assertRaises(exceptions.VnfHealFailed,
|
||||
driver.heal_vnf, self.context,
|
||||
vnf_instance, vnf_dict, heal_vnf_req)
|
||||
@ -814,6 +823,10 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
@mock.patch.object(driver_manager.DriverManager, "invoke")
|
||||
def test_scale_true(self, mock_invoke, mock_get_service_plugins):
|
||||
vnf_info = fakes._get_vnf()
|
||||
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
|
||||
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
|
||||
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
|
||||
'\"initialLevel\": 0, \"default\": 0 }}}'
|
||||
scale_vnf_request = fakes.scale_request("SCALE_IN", 1, "True")
|
||||
vim_connection_info = vim_connection.VimConnectionInfo(
|
||||
vim_type="fake_type")
|
||||
@ -830,6 +843,10 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
def test_scale_false_in(self, mock_invoke, mock_safe_load,
|
||||
mock_get_service_plugins):
|
||||
vnf_info = fakes._get_vnf()
|
||||
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
|
||||
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
|
||||
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
|
||||
'\"initialLevel\": 0, \"default\": 0 }}}'
|
||||
scale_vnf_request = fakes.scale_request("SCALE_IN", 1, "False")
|
||||
vim_connection_info = vim_connection.VimConnectionInfo(
|
||||
vim_type="fake_type")
|
||||
@ -846,9 +863,36 @@ class TestVnflcmDriver(db_base.SqlTestCase):
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(yaml, "safe_load")
|
||||
@mock.patch.object(driver_manager.DriverManager, "invoke")
|
||||
def test_scale_false_out(self, mock_invoke, mock_safe_load,
|
||||
def test_scale_false_out_initial(self, mock_invoke, mock_safe_load,
|
||||
mock_get_service_plugins):
|
||||
vnf_info = fakes._get_vnf()
|
||||
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
|
||||
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
|
||||
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
|
||||
'\"initialLevel\": 0, \"default\": 0 }}}'
|
||||
scale_vnf_request = fakes.scale_request("SCALE_OUT", 1, "False")
|
||||
vim_connection_info = vim_connection.VimConnectionInfo(
|
||||
vim_type="fake_type")
|
||||
scale_name_list = ["fake"]
|
||||
grp_id = "fake_id"
|
||||
with open(vnf_info["attributes"]["heat_template"], "r") as f:
|
||||
mock_safe_load.return_value = yaml.safe_load(f)
|
||||
print(mock_safe_load.return_value)
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
driver.scale(self.context, vnf_info, scale_vnf_request,
|
||||
vim_connection_info, scale_name_list, grp_id)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(yaml, "safe_load")
|
||||
@mock.patch.object(driver_manager.DriverManager, "invoke")
|
||||
def test_scale_false_out_level_up(self, mock_invoke, mock_safe_load,
|
||||
mock_get_service_plugins):
|
||||
vnf_info = fakes._get_vnf()
|
||||
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
|
||||
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
|
||||
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
|
||||
'\"initialLevel\": 0, \"default\": 1 }}}'
|
||||
scale_vnf_request = fakes.scale_request("SCALE_OUT", 1, "False")
|
||||
vim_connection_info = vim_connection.VimConnectionInfo(
|
||||
vim_type="fake_type")
|
||||
|
@ -0,0 +1,98 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: >
|
||||
Template for test _generate_hot_from_tosca().
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
|
||||
node_types:
|
||||
topology_template:
|
||||
node_templates:
|
||||
VDU1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU1
|
||||
description: VDU1 compute node
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: Software of VDU1
|
||||
version: '0.4.0'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 1 GiB
|
||||
size: 1 GiB
|
||||
artifacts:
|
||||
sw_image:
|
||||
type: tosca.artifacts.nfv.SwImage
|
||||
file: Files/images/cirros-0.4.0-x86_64-disk.img
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MiB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 1 GiB
|
||||
requirements:
|
||||
- virtual_storage: VB1
|
||||
|
||||
VB1:
|
||||
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
||||
properties:
|
||||
virtual_block_storage_data:
|
||||
size_of_storage: 100 GB
|
||||
rdma_enabled: true
|
||||
sw_image_data:
|
||||
name: cirros
|
||||
version: '0.0.0'
|
||||
checksum:
|
||||
algorithm: sha512
|
||||
hash: f0fd1b50420dce4ca382ccfbb528eef3a38bbeff00b54e95e3876b9bafe7ed2d6f919ca35d9046d437c6d2d8698b1174a335fbd66035bb3edc525d2cdb187232
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 B
|
||||
min_ram: 0 B
|
||||
size: 13267968 B
|
||||
|
||||
CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 0
|
||||
requirements:
|
||||
- virtual_binding: VDU1
|
||||
- virtual_link: VL3
|
||||
|
||||
VL3:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
description: Internal Virtual link in the VNF
|
||||
vl_profile:
|
||||
max_bitrate_requirements:
|
||||
root: 1048576
|
||||
leaf: 1048576
|
||||
min_bitrate_requirements:
|
||||
root: 1048576
|
||||
leaf: 1048576
|
||||
virtual_link_protocol_data:
|
||||
- associated_layer_protocol: ipv4
|
||||
l3_protocol_data:
|
||||
ip_version: ipv4
|
||||
cidr: 33.33.0.0/24
|
||||
|
||||
policies:
|
||||
- policy_affinity_local_VDU1:
|
||||
type: tosca.policies.nfv.AntiAffinityRule
|
||||
targets: [ VDU1 ]
|
||||
properties:
|
||||
scope: zone
|
@ -0,0 +1,27 @@
|
||||
heat_template_version: 2016-10-14
|
||||
description: test
|
||||
parameters:
|
||||
DB11_image:
|
||||
type: string
|
||||
default: cirros
|
||||
resources:
|
||||
DB11:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
user_data_format: SOFTWARE_CONFIG
|
||||
availability_zone: nova
|
||||
block_device_mapping_v2:
|
||||
- device_name: vda
|
||||
volume_id: {get_resource: ST1}
|
||||
flavor: m1.tiny
|
||||
networks:
|
||||
- port: {get_resource: DB11-CP}
|
||||
config_drive: false
|
||||
DB11-CP:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: net_mgmt
|
||||
outputs:
|
||||
id-DB11:
|
||||
value:
|
||||
get_attr: [DB11-CP, fixed_ips, 0, ip_address]
|
@ -0,0 +1,31 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: test
|
||||
parameters:
|
||||
current_num:
|
||||
type: number
|
||||
nfv:
|
||||
type: json
|
||||
resources:
|
||||
SP1_scale_out:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
auto_scaling_group_id: {get_resource: SP1_group}
|
||||
adjustment_type: change_in_capacity
|
||||
scaling_adjustment: 1
|
||||
SP1_group:
|
||||
type: OS::Heat::AutoScalingGroup
|
||||
properties:
|
||||
min_size: 0
|
||||
desired_capacity: {get_param: current_num}
|
||||
resource:
|
||||
type: SP1_res.yaml
|
||||
properties:
|
||||
nfv: {get_param: nfv}
|
||||
max_size: 3
|
||||
SP1_scale_in:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
auto_scaling_group_id: {get_resource: SP1_group}
|
||||
adjustment_type: change_in_capacity
|
||||
scaling_adjustment: -1
|
||||
outputs: {}
|
@ -0,0 +1,31 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: test
|
||||
parameters:
|
||||
current_num:
|
||||
type: number
|
||||
nfv:
|
||||
type: json
|
||||
resources:
|
||||
SP1_scale_out:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
auto_scaling_group_id: {get_resource: SP1_group}
|
||||
adjustment_type: change_in_capacity
|
||||
scaling_adjustment: 1
|
||||
SP1_group:
|
||||
type: OS::Heat::AutoScalingGroup
|
||||
properties:
|
||||
min_size: 0
|
||||
desired_capacity: {get_param: current_num}
|
||||
resource:
|
||||
type: SP1_res.yaml
|
||||
properties:
|
||||
nfv: {get_param: nfv}
|
||||
max_size: 3
|
||||
SP1_scale_in:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
auto_scaling_group_id: {get_resource: SP1_group}
|
||||
adjustment_type: change_in_capacity
|
||||
scaling_adjustment: -1
|
||||
outputs: {}
|
@ -0,0 +1,57 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: test
|
||||
parameters:
|
||||
DB11_image:
|
||||
type: string
|
||||
default: cirros
|
||||
my_compute_placement_policy:
|
||||
type: string
|
||||
default: ssss
|
||||
resources:
|
||||
DB11:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
user_data_format: SOFTWARE_CONFIG
|
||||
availability_zone: nova
|
||||
scheduler_hints:
|
||||
group: {get_resource: my_compute_placement_policy}
|
||||
block_device_mapping_v2:
|
||||
- device_name: vda
|
||||
volume_id: {get_resource: ENUMm0-VB}
|
||||
flavor: m1.tiny
|
||||
networks:
|
||||
- port: {get_resource: DB11-CP}
|
||||
config_drive: false
|
||||
DB11-CP:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: {get_resource: DB11-VL}
|
||||
DB12:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
user_data_format: SOFTWARE_CONFIG
|
||||
availability_zone: nova
|
||||
image: cirros
|
||||
flavor: m1.tiny
|
||||
networks:
|
||||
- port: {get_resource: DB12-CP}
|
||||
config_drive: false
|
||||
DB12-CP:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: {get_resource: DB11-VL}
|
||||
DB12-VB:
|
||||
properties: {image: cirros, size: \'1\'}
|
||||
type: OS::Cinder::Volume
|
||||
ENUMm0-VB:
|
||||
properties:
|
||||
image: {get_param: DB11_image}
|
||||
size: \'1\'
|
||||
type: OS::Cinder::Volume
|
||||
DB12-CB:
|
||||
properties:
|
||||
instance_uuid: {get_resource: DB12}
|
||||
mountpoint: /dev/vdb
|
||||
volume_id: {get_resource: DB12-VB}
|
||||
type: OS::Cinder::VolumeAttachment
|
||||
outputs: {}
|
@ -0,0 +1,27 @@
|
||||
heat_template_version: 2016-10-14
|
||||
description: test
|
||||
parameters:
|
||||
DB11_image:
|
||||
type: string
|
||||
default: cirros
|
||||
resources:
|
||||
DB11:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
user_data_format: SOFTWARE_CONFIG
|
||||
availability_zone: nova
|
||||
block_device_mapping_v2:
|
||||
- device_name: vda
|
||||
volume_id: {get_resource: ST1}
|
||||
flavor: m1.tiny
|
||||
networks:
|
||||
- port: {get_resource: DB11-CP}
|
||||
config_drive: false
|
||||
DB11-CP:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: net_mgmt
|
||||
outputs:
|
||||
id-DB11:
|
||||
value:
|
||||
get_attr: [DB11-CP, fixed_ips, 0, ip_address]
|
@ -23,8 +23,12 @@ import ddt
|
||||
import requests
|
||||
import yaml
|
||||
|
||||
from heatclient.v1 import resources
|
||||
from oslo_serialization import jsonutils
|
||||
from tacker.common import exceptions
|
||||
from tacker.common import utils as cutils
|
||||
from tacker import context
|
||||
from tacker.db.db_sqlalchemy import models
|
||||
from tacker.extensions import vnfm
|
||||
from tacker import objects
|
||||
from tacker.tests.common import helpers
|
||||
@ -39,6 +43,21 @@ from tacker.vnfm.infra_drivers.openstack import heat_client as hc
|
||||
from tacker.vnfm.infra_drivers.openstack import openstack
|
||||
|
||||
|
||||
vnf_dict = {
|
||||
'instance_id': 'd1121d3c-368b-4ac2-b39d-835aa3e4ccd8'
|
||||
}
|
||||
|
||||
|
||||
class FakeAlarmPlugin():
|
||||
def add_alarm_url_to_vnf(self, context, vnf):
|
||||
return
|
||||
|
||||
|
||||
class FakePlugin():
|
||||
def get_vnf(self, context, id):
|
||||
return vnf_dict
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestOpenStack(base.FixturedTestCase):
|
||||
client_fixture_class = client.ClientFixture
|
||||
@ -144,7 +163,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
mock_get_base_hot_dict,
|
||||
mock_get_vnflcm_interface,
|
||||
mock_format_base_hot):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -156,7 +176,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
'instantiate_vnf_request_lcm_userdata.json')
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
vnf_resource = type('', (), {})
|
||||
vnf_resource.resource_identifier = constants.INVALID_UUID
|
||||
grant_info_test = {'vdu_name': {vnf_resource}}
|
||||
@ -171,6 +191,105 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
grant_info=grant_info_test,
|
||||
vnf_instance=vnf_instance)
|
||||
|
||||
@mock.patch('tacker.vnfm.infra_drivers.openstack.openstack'
|
||||
'.OpenStack._format_base_hot')
|
||||
@mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict')
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_grant(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict,
|
||||
mock_format_base_hot):
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__),
|
||||
"../../../../etc/samples/etsi/nfv",
|
||||
"user_data_sample_normal"))
|
||||
inst_req_info_test = type('', (), {})
|
||||
test_json = self._json_load(
|
||||
'instantiate_vnf_request_lcm_userdata.json')
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
vnf_resource = type('', (), {})
|
||||
vnf_resource.resource_identifier = constants.INVALID_UUID
|
||||
grant_info_test = {'vdu_name': {vnf_resource}}
|
||||
nested_hot_dict = {'parameters': {'vnf': 'test'}}
|
||||
mock_get_base_hot_dict.return_value = \
|
||||
self._read_file(), nested_hot_dict
|
||||
vimAssets = {'compute_resource_flavours': [
|
||||
{'vim_connection_id': uuidsentinel.vim_id,
|
||||
'vnfd_virtual_compute_desc_id': 'VDU1',
|
||||
'vim_flavour_id': 'm1.tiny'}],
|
||||
'softwareImages': [
|
||||
{'vim_connection_id': uuidsentinel.vim_id,
|
||||
'vnfd_software_image_id': 'VDU1',
|
||||
'vim_software_image_id': 'cirros'}]}
|
||||
resAddResource = []
|
||||
resource = {
|
||||
'resource_definition_id': '2c6e5cc7-240d-4458-a683-1fe648351280',
|
||||
'vim_connection_id': uuidsentinel.vim_id,
|
||||
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
|
||||
resAddResource.append(resource)
|
||||
resource = {
|
||||
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa9',
|
||||
'vim_connection_id': uuidsentinel.vim_id,
|
||||
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
|
||||
resAddResource.append(resource)
|
||||
resource = {
|
||||
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa0',
|
||||
'vim_connection_id': uuidsentinel.vim_id,
|
||||
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
|
||||
resAddResource.append(resource)
|
||||
resource = {
|
||||
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa1',
|
||||
'vim_connection_id': uuidsentinel.vim_id,
|
||||
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
|
||||
resAddResource.append(resource)
|
||||
zone = {
|
||||
'id': '5e4da3c3-4a55-412a-b624-843921f8b51d',
|
||||
'zone_id': 'nova',
|
||||
'vim_connection_id': uuidsentinel.vim_id}
|
||||
vim_obj = {'id': '0b9c66bb-9e1f-4bb2-92c3-913074e52e2b',
|
||||
'vim_id': uuidsentinel.vim_id,
|
||||
'vim_type': 'openstack',
|
||||
'access_info': {
|
||||
'password': 'test_pw',
|
||||
'username': 'test_user',
|
||||
'region': 'test_region',
|
||||
'tenant': uuidsentinel.tenant}}
|
||||
grant_dict = {}
|
||||
grant_dict['id'] = 'c213e465-8220-487e-9464-f79104e81e96'
|
||||
grant_dict['vnf_instance_id'] = uuidsentinel.vnf_instance_id
|
||||
grant_dict['vnf_lcm_op_occ_id'] = uuidsentinel.vnf_lcm_op_occ_id
|
||||
grant_dict['add_resources'] = []
|
||||
grant_dict['add_resources'].extend(resAddResource)
|
||||
grant_dict['vim_assets'] = vimAssets
|
||||
grant_dict['zones'] = [zone]
|
||||
grant_dict['vim_connections'] = [vim_obj]
|
||||
grant_obj = objects.Grant.obj_from_primitive(
|
||||
grant_dict, context=self.context)
|
||||
vnf['grant'] = grant_obj
|
||||
vnf_instance = fd_utils.get_vnf_instance_object()
|
||||
vnf_instance.instantiated_vnf_info.reinitialize()
|
||||
vnfc_obj = objects.VnfcResourceInfo()
|
||||
vnfc_obj.id = '2c6e5cc7-240d-4458-a683-1fe648351280'
|
||||
vnfc_obj.vdu_id = 'VDU1'
|
||||
vnfc_obj.storage_resource_ids = \
|
||||
['faf14707-da7c-4eec-be99-8099fa1e9fa0']
|
||||
compute_resource = objects.ResourceHandle(
|
||||
vim_connection_id=uuidsentinel.vim_id,
|
||||
resource_id='6e1c286d-c023-4b34-8369-831c6e84cce2')
|
||||
vnfc_obj.compute_resource = compute_resource
|
||||
vnf_instance.instantiated_vnf_info.vnfc_resource_info = [vnfc_obj]
|
||||
self.openstack.create(self.plugin, self.context, vnf,
|
||||
self.auth_attr, inst_req_info=inst_req_info_test,
|
||||
vnf_package_path=vnf_package_path_test,
|
||||
base_hot_dict=base_hot_dict_test,
|
||||
grant_info=grant_info_test,
|
||||
vnf_instance=vnf_instance)
|
||||
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_heat_stack(self, mock_OpenstackClients_heat):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
@ -236,7 +355,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_userdata_null(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -251,7 +371,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
grant_info_test = None
|
||||
nested_hot_dict = {'test': 'test'}
|
||||
mock_get_base_hot_dict.return_value = \
|
||||
@ -270,7 +390,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_userdataclass_null(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -285,7 +406,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
grant_info_test = None
|
||||
nested_hot_dict = {'test': 'test'}
|
||||
mock_get_base_hot_dict.return_value = \
|
||||
@ -304,7 +425,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_import_module_exception(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -316,7 +438,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
'instantiate_vnf_request_lcm_userdata.json')
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
grant_info_test = None
|
||||
nested_hot_dict = {'test': 'test'}
|
||||
mock_get_base_hot_dict.return_value = \
|
||||
@ -337,7 +459,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_getattr_none(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -370,7 +493,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_missing_file(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -382,7 +506,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
'instantiate_vnf_request_lcm_userdata.json')
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
vnf_resource = type('', (), {})
|
||||
vnf_resource.resource_identifier = constants.INVALID_UUID
|
||||
grant_info_test = {'vdu_name': {vnf_resource}}
|
||||
@ -403,7 +527,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_return_none_dict(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -417,7 +542,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
'UserData/lcm_user_data_non_dict.py'
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
vnf_resource = type('', (), {})
|
||||
vnf_resource.resource_identifier = constants.INVALID_UUID
|
||||
grant_info_test = {'vdu_name': {vnf_resource}}
|
||||
@ -438,7 +563,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_none_base_hot_dict(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
inst_req_info_test = type('', (), {})
|
||||
test_json = self._json_load(
|
||||
@ -465,7 +591,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_invalid_user_data(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -481,7 +608,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
grant_info_test = None
|
||||
nested_hot_dict = {'test': 'test'}
|
||||
mock_get_base_hot_dict.return_value = \
|
||||
@ -501,7 +628,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
def test_create_invalid_user_data_class(self,
|
||||
mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -517,7 +645,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
grant_info_test = None
|
||||
nested_hot_dict = {'test': 'test'}
|
||||
mock_get_base_hot_dict.return_value = \
|
||||
@ -536,7 +664,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_lcm_user_data_and_user_data_class_no_value(self,
|
||||
mock_OpenstackClients_heat, mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -553,7 +682,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = test_json['extVirtualLinks']
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
vnf_resource = type('', (), {})
|
||||
vnf_resource.resource_identifier = constants.INVALID_UUID
|
||||
grant_info_test = {'vdu_name': {vnf_resource}}
|
||||
@ -620,7 +749,8 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
@mock.patch('tacker.common.clients.OpenstackClients')
|
||||
def test_create_instance_exception(self, mock_OpenstackClients_heat,
|
||||
mock_get_base_hot_dict):
|
||||
vnf = utils.get_dummy_vnf(instance_id=self.instance_uuid)
|
||||
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
|
||||
flavour='simple')
|
||||
vnf['placement_attr'] = {'region_name': 'dummy_region'}
|
||||
base_hot_dict_test = self._read_file()
|
||||
vnf_package_path_test = os.path.abspath(
|
||||
@ -634,7 +764,7 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
'UserData/lcm_user_data_invalid_script.py'
|
||||
inst_req_info_test.additional_params = test_json['additionalParams']
|
||||
inst_req_info_test.ext_virtual_links = None
|
||||
inst_req_info_test.flavour_id = test_json['flavourId']
|
||||
inst_req_info_test.flavour_id = 'simple'
|
||||
vnf_resource = type('', (), {})
|
||||
vnf_resource.resource_identifier = constants.INVALID_UUID
|
||||
grant_info_test = {'vdu_name': {vnf_resource}}
|
||||
@ -1633,3 +1763,190 @@ class TestOpenStack(base.FixturedTestCase):
|
||||
"stack_id %s") % (vnf_instance.id,
|
||||
uuidsentinel.stack_id)
|
||||
self.assertEqual(expected_msg, str(result))
|
||||
|
||||
def test_get_grant_resource_scale_out(self):
|
||||
vnfc_resource_info = fd_utils.get_vnfc_resource_info()
|
||||
|
||||
inst_vnf_info = fd_utils.get_vnf_instantiated_info(
|
||||
vnfc_resource_info=[vnfc_resource_info])
|
||||
|
||||
vnf_instance = fd_utils.get_vnf_instance_object(
|
||||
instantiated_vnf_info=inst_vnf_info)
|
||||
|
||||
vim_connection_info = fd_utils.get_vim_connection_info_object()
|
||||
scale_vnf_request = objects.ScaleVnfRequest(type='SCALE_OUT',
|
||||
aspect_id='SP1',
|
||||
number_of_steps=1)
|
||||
test_res = '[{"id_type": "RES_MGMT", "resource_id": ' + \
|
||||
'"2c6e5cc7-240d-4458-a683-1fe648351200",' + \
|
||||
' "vim_connection_id": ' + \
|
||||
'"2a63bee3-0c43-4568-bcfa-b0cb733e064c"}]'
|
||||
placemnt = models.PlacementConstraint(
|
||||
id='c2947d8a-2c67-4e8f-ad6f-c0889b351c17',
|
||||
vnf_instance_id=uuidsentinel.vnf_instance_id,
|
||||
affinity_or_anti_affinity='ANTI_AFFINITY',
|
||||
scope='ZONE',
|
||||
server_group_name='my_compute_placement_policy',
|
||||
resource=test_res)
|
||||
placement_obj_list = [placemnt]
|
||||
del_list = []
|
||||
vnf_info = {}
|
||||
vnf_info['attributes'] = {}
|
||||
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
|
||||
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
|
||||
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
|
||||
'\"initialLevel\": 0, \"default\": 0 }}}'
|
||||
vnf_info['attributes']['heat_template'] = utils.\
|
||||
get_dummy_scale_grant_hot()
|
||||
vnf_info['attributes']['SP1_res.yaml'] = utils.\
|
||||
get_dummy_scale_nest_grant_hot()
|
||||
self.openstack.get_grant_resource(
|
||||
vnf_instance,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
placement_obj_list,
|
||||
vim_connection_info,
|
||||
del_list)
|
||||
self.assertEqual(1, len(vnf_info['placement_constraint_list']))
|
||||
|
||||
@mock.patch.object(hc.HeatClient, "resource_get_list")
|
||||
def test_get_grant_resource_scale_in(self, mock_list):
|
||||
v_s_resource_info = fd_utils.get_virtual_storage_resource_info(
|
||||
desc_id="storage1", set_resource_id=False)
|
||||
|
||||
storage_resource_ids = [v_s_resource_info.id]
|
||||
vnfc_resource_info = fd_utils.get_vnfc_resource_info(vdu_id="VDU_VNF",
|
||||
storage_resource_ids=storage_resource_ids, set_resource_id=False)
|
||||
|
||||
v_l_resource_info = fd_utils.get_virtual_link_resource_info(
|
||||
vnfc_resource_info.vnfc_cp_info[0].vnf_link_port_id,
|
||||
vnfc_resource_info.vnfc_cp_info[0].id)
|
||||
|
||||
inst_vnf_info = fd_utils.get_vnf_instantiated_info(
|
||||
virtual_storage_resource_info=[v_s_resource_info],
|
||||
vnf_virtual_link_resource_info=[v_l_resource_info],
|
||||
vnfc_resource_info=[vnfc_resource_info])
|
||||
|
||||
vnf_instance = fd_utils.get_vnf_instance_object(
|
||||
instantiated_vnf_info=inst_vnf_info)
|
||||
|
||||
vim_connection_info = fd_utils.get_vim_connection_info_object()
|
||||
scale_vnf_request = objects.ScaleVnfRequest(type='SCALE_IN',
|
||||
aspect_id='SP1',
|
||||
number_of_steps=1)
|
||||
placement_obj_list = []
|
||||
del_list = ['58337c61-3148-4c29-892f-68b043c009ea']
|
||||
vnf_info = {}
|
||||
res_list = []
|
||||
vdu_id = uuidsentinel.vdu_resource_id
|
||||
vnf_instance.instantiated_vnf_info.vnfc_resource_info[0].\
|
||||
compute_resource.resource_id = vdu_id
|
||||
resource2 = resources.Resource(None, {
|
||||
'resource_name': 'aaaaaaaa',
|
||||
'resource_type': 'OS::Nova::Server',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': vdu_id,
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource2)
|
||||
port_id = uuidsentinel.virtual_link_port_resource_id
|
||||
vnf_instance.instantiated_vnf_info.vnf_virtual_link_resource_info[
|
||||
0].vnf_link_ports[0].resource_handle.resource_id = port_id
|
||||
resource3 = resources.Resource(None, {
|
||||
'resource_name': 'bbbbbbbb',
|
||||
'resource_type': 'OS::Neutron::Port',
|
||||
'creation_time': '2020-01-01T00:00:00',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': port_id,
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource3)
|
||||
st_id = uuidsentinel.vdu_resource_id
|
||||
vnf_instance.instantiated_vnf_info.virtual_storage_resource_info[
|
||||
0].storage_resource.resource_id = st_id
|
||||
resource4 = resources.Resource(None, {
|
||||
'resource_name': 'cccccccc',
|
||||
'resource_type': 'OS::Cinder::Volume',
|
||||
'creation_time': '2020-01-01T00:00:01',
|
||||
'resource_status': 'CREATE_COMPLETE',
|
||||
'physical_resource_id': st_id,
|
||||
'id': '1111'
|
||||
})
|
||||
res_list.append(resource4)
|
||||
mock_list.return_value = res_list
|
||||
self.openstack.get_grant_resource(
|
||||
vnf_instance,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
placement_obj_list,
|
||||
vim_connection_info,
|
||||
del_list)
|
||||
self.assertEqual(3, len(vnf_info['removeResources']))
|
||||
|
||||
@mock.patch.object(hc.HeatClient, "update")
|
||||
def test_scale_out_initial(self, mock_update):
|
||||
scale_vnf_request = objects.ScaleVnfRequest(type='SCALE_OUT',
|
||||
aspect_id='SP1',
|
||||
number_of_steps=1)
|
||||
vnf_info = {}
|
||||
vnf_info['attributes'] = {}
|
||||
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
|
||||
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
|
||||
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
|
||||
'\"initialLevel\": 0, \"default\": 0 }}}'
|
||||
vnf_info['attributes']['heat_template'] = \
|
||||
utils.get_dummy_scale_initial_hot()
|
||||
vnf_info['attributes']['SP1_res.yaml'] = \
|
||||
utils.get_dummy_scale_nest_initial_hot()
|
||||
stack_param_dict = {}
|
||||
stack_param_dict['nfv'] = {}
|
||||
stack_param_dict['nfv']['VDU'] = {}
|
||||
stack_param_dict['nfv']['VDU']['VDU1'] = {}
|
||||
stack_param_dict['nfv']['VDU']['VDU1']['zone'] = ''
|
||||
stack_param_dict['nfv']['VDU']['VDU1']['flavor'] = ''
|
||||
stack_param_dict['nfv']['VDU']['VDU1']['image'] = ''
|
||||
vnf_info['attributes'].update({'stack_param': str(stack_param_dict)})
|
||||
vnf_info['instance_id'] = uuidsentinel.stack_id
|
||||
testjson = '{"id": "c213e465-8220-487e-9464-f79104e81e96", ' + \
|
||||
'"vnf_instance_id": ' + \
|
||||
'"47101fb6-bd18-4e04-b2b5-22370a023448", ' + \
|
||||
'"vnf_lcm_op_occ_id": ' + \
|
||||
'"f26f181d-7891-4720-b022-b074ec1733ef", ' + \
|
||||
'"add_resources": [{"resource_definition_id": ' + \
|
||||
'"2c6e5cc7-240d-4458-a683-1fe648351280", ' + \
|
||||
'"vim_connection_id": ' + \
|
||||
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
|
||||
'"zone_id": "5e4da3c3-4a55-412a-b624-843921f8b51d"}' + \
|
||||
', {"resource_definition_id": ' + \
|
||||
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
|
||||
'"vim_connection_id": ' + \
|
||||
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
|
||||
'"zone_id": "5e4da3c3-4a55-412a-b624-843921f8b51d"}' + \
|
||||
', {"resource_definition_id": ' + \
|
||||
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
|
||||
'"vim_connection_id": ' + \
|
||||
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
|
||||
'"zone_id": ' + \
|
||||
'"5e4da3c3-4a55-412a-b624-843921f8b51d"}], ' + \
|
||||
'"vim_assets": {"compute_resource_flavours": ' + \
|
||||
'[{"vim_connection_id": ' + \
|
||||
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
|
||||
'"vnfd_virtual_compute_desc_id": "VDU1", ' + \
|
||||
'"vim_flavour_id": "m1.tiny"}], "software_images": ' + \
|
||||
'[{"vim_connection_id": ' + \
|
||||
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
|
||||
'"vnfd_software_image_id": "VDU1", ' + \
|
||||
'"vim_software_image_id": "cirros"}]}}'
|
||||
res_body = jsonutils.loads(testjson)
|
||||
res_dict = cutils.convert_camelcase_to_snakecase(res_body)
|
||||
grant_obj = objects.Grant.obj_from_primitive(
|
||||
res_dict, context=context)
|
||||
vnf_info['grant'] = grant_obj
|
||||
self.openstack.scale_out_initial(context=self.context,
|
||||
plugin=self,
|
||||
auth_attr=None,
|
||||
vnf_info=vnf_info,
|
||||
scale_vnf_request=scale_vnf_request,
|
||||
region_name=None
|
||||
)
|
||||
|
@ -18,6 +18,7 @@ from unittest import mock
|
||||
from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import iso8601
|
||||
from oslo_utils import uuidutils
|
||||
import yaml
|
||||
|
||||
@ -25,12 +26,15 @@ from tacker._i18n import _
|
||||
from tacker.common import exceptions
|
||||
from tacker import context
|
||||
from tacker.db.common_services import common_services_db_plugin
|
||||
from tacker.db.db_sqlalchemy import models
|
||||
from tacker.db.nfvo import nfvo_db
|
||||
from tacker.db.nfvo import ns_db
|
||||
from tacker.db.vnfm import vnfm_db
|
||||
from tacker.extensions import vnfm
|
||||
from tacker import objects
|
||||
from tacker.objects import heal_vnf_request
|
||||
from tacker.plugins.common import constants
|
||||
from tacker.tests.unit.conductor import fakes
|
||||
from tacker.tests.unit.db import base as db_base
|
||||
from tacker.tests.unit.db import utils
|
||||
from tacker.vnfm import monitor
|
||||
@ -1160,3 +1164,165 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
||||
mock_get_vnf.return_value = dummy_vnf
|
||||
self._test_create_vnf_trigger(policy_name="start_actions",
|
||||
action_value="SP_RSV-out")
|
||||
|
||||
def test_create_placement_constraint(self):
|
||||
res_str = '[{"id_type": "RES_MGMT", "resource_id": ' + \
|
||||
'"2c6e5cc7-240d-4458-a683-1fe648351200", ' + \
|
||||
'"vim_connection_id": ' + \
|
||||
'"2a63bee3-0c43-4568-bcfa-b0cb733e064c"}]'
|
||||
placemnt = models.PlacementConstraint(
|
||||
id='c2947d8a-2c67-4e8f-ad6f-c0889b351c17',
|
||||
vnf_instance_id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
affinity_or_anti_affinity='ANTI_AFFINITY',
|
||||
scope='ZONE',
|
||||
server_group_name='my_compute_placement_policy',
|
||||
resource=res_str,
|
||||
deleted_at=datetime.min)
|
||||
pls_list = [placemnt]
|
||||
vnf_inst = models.VnfInstance(
|
||||
id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
vnf_provider=' ',
|
||||
vnf_product_name=' ',
|
||||
vnf_software_version=' ',
|
||||
vnfd_version=' ',
|
||||
vnfd_id='8d86480e-d4e6-4ee0-ba4d-08217118d6cb',
|
||||
instantiation_state=' ',
|
||||
tenant_id='9b3f0518-bf6b-4982-af32-d282ce577c8f',
|
||||
created_at=datetime(
|
||||
2020, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_pkg_id=uuidutils.generate_uuid())
|
||||
self.context.session.add(vnf_inst)
|
||||
self.context.session.flush()
|
||||
|
||||
self.vnfm_plugin.create_placement_constraint(
|
||||
self.context, pls_list)
|
||||
|
||||
def test_get_placement_constraint(self):
|
||||
res_str = '[{"id_type": "RES_MGMT", "resource_id": ' + \
|
||||
'"2c6e5cc7-240d-4458-a683-1fe648351200", ' + \
|
||||
'"vim_connection_id": ' + \
|
||||
'"2a63bee3-0c43-4568-bcfa-b0cb733e064c"}]'
|
||||
placemnt = models.PlacementConstraint(
|
||||
id='c2947d8a-2c67-4e8f-ad6f-c0889b351c17',
|
||||
vnf_instance_id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
affinity_or_anti_affinity='ANTI_AFFINITY',
|
||||
scope='ZONE',
|
||||
server_group_name='my_compute_placement_policy',
|
||||
resource=res_str,
|
||||
deleted_at=datetime.min)
|
||||
vnf_inst = models.VnfInstance(
|
||||
id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
vnf_provider=' ',
|
||||
vnf_product_name=' ',
|
||||
vnf_software_version=' ',
|
||||
vnfd_version=' ',
|
||||
vnfd_id='8d86480e-d4e6-4ee0-ba4d-08217118d6cb',
|
||||
instantiation_state=' ',
|
||||
tenant_id='9b3f0518-bf6b-4982-af32-d282ce577c8f',
|
||||
created_at=datetime(
|
||||
2020, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_pkg_id=uuidutils.generate_uuid())
|
||||
self.context.session.add(vnf_inst)
|
||||
self.context.session.flush()
|
||||
self.context.session.add(placemnt)
|
||||
self.context.session.flush()
|
||||
|
||||
res = self.vnfm_plugin.get_placement_constraint(
|
||||
self.context, '7ddc38c3-a116-48b0-bfc1-68d7f306f467')
|
||||
self.assertEqual(1, len(res))
|
||||
|
||||
def test_update_placement_constraint_heal(self):
|
||||
res_str = '[{"id_type": "RES_MGMT", "resource_id": ' + \
|
||||
'"2c6e5cc7-240d-4458-a683-1fe648351200", ' + \
|
||||
'"vim_connection_id": ' + \
|
||||
'"2a63bee3-0c43-4568-bcfa-b0cb733e064c"}]'
|
||||
placemnt = models.PlacementConstraint(
|
||||
id='c2947d8a-2c67-4e8f-ad6f-c0889b351c17',
|
||||
vnf_instance_id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
affinity_or_anti_affinity='ANTI_AFFINITY',
|
||||
scope='ZONE',
|
||||
server_group_name='my_compute_placement_policy',
|
||||
resource=res_str,
|
||||
deleted_at=datetime.min)
|
||||
res_str2 = '[{"id_type": "GRANT", "resource_id": ' + \
|
||||
'"4cef1b7e-8e5f-430e-b32e-a7585a61d61c"}]'
|
||||
placemnt2 = models.PlacementConstraint(
|
||||
id='c2947d8a-2c67-4e8f-ad6f-c0889b351c17',
|
||||
vnf_instance_id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
affinity_or_anti_affinity='ANTI_AFFINITY',
|
||||
scope='ZONE',
|
||||
server_group_name='my_compute_placement_policy',
|
||||
resource=res_str2,
|
||||
deleted_at=datetime.min)
|
||||
vnf_inst = models.VnfInstance(
|
||||
id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
vnf_provider=' ',
|
||||
vnf_product_name=' ',
|
||||
vnf_software_version=' ',
|
||||
vnfd_version=' ',
|
||||
vnfd_id='8d86480e-d4e6-4ee0-ba4d-08217118d6cb',
|
||||
instantiation_state=' ',
|
||||
tenant_id='9b3f0518-bf6b-4982-af32-d282ce577c8f',
|
||||
created_at=datetime(
|
||||
2020, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_pkg_id=uuidutils.generate_uuid())
|
||||
self.context.session.add(vnf_inst)
|
||||
self.context.session.flush()
|
||||
self.context.session.add(placemnt)
|
||||
self.context.session.flush()
|
||||
|
||||
vnf_info = {}
|
||||
vnf_info['grant'] = objects.Grant()
|
||||
placement_obj_list = []
|
||||
placement_obj_list.append(placemnt2)
|
||||
vnf_info['placement_obj_list'] = placement_obj_list
|
||||
|
||||
insta = fakes.return_vnf_instance('INSTANTIATED')
|
||||
vnfc = objects.VnfcResourceInfo()
|
||||
vnfc.id = '4cef1b7e-8e5f-430e-b32e-a7585a61d61c'
|
||||
vnfc.vdu_id = 'VDU1'
|
||||
c_rsc = objects.ResourceHandle()
|
||||
c_rsc.vim_connection_id = '2a63bee3-0c43-4568-bcfa-b0cb733e064c'
|
||||
c_rsc.resource_id = '9aa1e075-2aa1-46ce-a27a-35a581190219'
|
||||
vnfc.compute_resource = c_rsc
|
||||
insta.instantiated_vnf_info.vnfc_resource_info.append(vnfc)
|
||||
|
||||
self.vnfm_plugin.update_placement_constraint_heal(
|
||||
self.context, vnf_info, insta)
|
||||
|
||||
def test_delete_placement_constraint(self):
|
||||
res_str = '[{"id_type": "RES_MGMT", "resource_id": ' + \
|
||||
'"2c6e5cc7-240d-4458-a683-1fe648351200", ' + \
|
||||
'"vim_connection_id": ' + \
|
||||
'"2a63bee3-0c43-4568-bcfa-b0cb733e064c"}]'
|
||||
placemnt = models.PlacementConstraint(
|
||||
id='c2947d8a-2c67-4e8f-ad6f-c0889b351c17',
|
||||
vnf_instance_id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
affinity_or_anti_affinity='ANTI_AFFINITY',
|
||||
scope='ZONE',
|
||||
server_group_name='my_compute_placement_policy',
|
||||
resource=res_str,
|
||||
deleted_at=datetime.min)
|
||||
vnf_inst = models.VnfInstance(
|
||||
id='7ddc38c3-a116-48b0-bfc1-68d7f306f467',
|
||||
vnf_provider=' ',
|
||||
vnf_product_name=' ',
|
||||
vnf_software_version=' ',
|
||||
vnfd_version=' ',
|
||||
vnfd_id='8d86480e-d4e6-4ee0-ba4d-08217118d6cb',
|
||||
instantiation_state=' ',
|
||||
tenant_id='9b3f0518-bf6b-4982-af32-d282ce577c8f',
|
||||
created_at=datetime(
|
||||
2020, 1, 1, 1, 1, 1,
|
||||
tzinfo=iso8601.UTC),
|
||||
vnf_pkg_id=uuidutils.generate_uuid())
|
||||
self.context.session.add(vnf_inst)
|
||||
self.context.session.flush()
|
||||
self.context.session.add(placemnt)
|
||||
self.context.session.flush()
|
||||
|
||||
self.vnfm_plugin.delete_placement_constraint(
|
||||
self.context, '7ddc38c3-a116-48b0-bfc1-68d7f306f467')
|
||||
|
@ -95,9 +95,11 @@ def _get_vnflcm_interface(context, interface, vnf_instance, flavour_id):
|
||||
if vnfd_dict.get('topology_template'):
|
||||
topology_template = vnfd_dict.get('topology_template')
|
||||
if topology_template.get('node_templates'):
|
||||
for a_val in topology_template.get('node_templates').values():
|
||||
if 'interfaces' in a_val.keys():
|
||||
interfaces = a_val.get('interfaces')
|
||||
node_templates = topology_template.get('node_templates')
|
||||
if node_templates.get('VNF'):
|
||||
vnf = node_templates.get('VNF')
|
||||
if vnf.get('interfaces'):
|
||||
interfaces = vnf.get('interfaces')
|
||||
if interfaces.get('Vnflcm'):
|
||||
vnflcm = interfaces.get('Vnflcm')
|
||||
if vnflcm:
|
||||
|
@ -276,7 +276,8 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
try:
|
||||
instance_id = self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type, 'instantiate_vnf',
|
||||
context=context, vnf_instance=vnf_instance,
|
||||
context=context, plugin=self._vnfm_plugin,
|
||||
vnf_instance=vnf_instance,
|
||||
vnfd_dict=final_vnf_dict, grant_response=vnf_resources,
|
||||
vim_connection_info=vim_connection_info,
|
||||
base_hot_dict=base_hot_dict,
|
||||
@ -293,12 +294,9 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
id=vnf_instance.id,
|
||||
error=encodeutils.exception_to_unicode(exp))
|
||||
|
||||
vnf_instance.instantiated_vnf_info = objects.InstantiatedVnfInfo(
|
||||
flavour_id=instantiate_vnf_req.flavour_id,
|
||||
instantiation_level_id=instantiate_vnf_req.instantiation_level_id,
|
||||
vnf_instance_id=vnf_instance.id,
|
||||
instance_id=instance_id,
|
||||
ext_cp_info=[])
|
||||
if vnf_instance.instantiated_vnf_info and\
|
||||
not vnf_instance.instantiated_vnf_info.instance_id:
|
||||
vnf_instance.instantiated_vnf_info.instance_id = instance_id
|
||||
if vnf_dict['attributes'].get('scaling_group_names'):
|
||||
vnf_instance.instantiated_vnf_info.scale_status = \
|
||||
vnf_dict['scale_status']
|
||||
@ -306,7 +304,7 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
try:
|
||||
self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type, 'create_wait',
|
||||
plugin=self, context=context,
|
||||
plugin=self._vnfm_plugin, context=context,
|
||||
vnf_dict=final_vnf_dict,
|
||||
vnf_id=final_vnf_dict['instance_id'],
|
||||
auth_attr=vim_connection_info.access_info)
|
||||
@ -322,14 +320,6 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
id=vnf_instance.id,
|
||||
error=encodeutils.exception_to_unicode(exp))
|
||||
|
||||
vnflcm_utils._build_instantiated_vnf_info(vnfd_dict,
|
||||
instantiate_vnf_req, vnf_instance, vim_connection_info.vim_id)
|
||||
|
||||
self._vnf_manager.invoke(vim_connection_info.vim_type,
|
||||
'post_vnf_instantiation', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
vim_connection_info=vim_connection_info)
|
||||
|
||||
@log.log
|
||||
@rollback_vnf_instantiated_resources
|
||||
def instantiate_vnf(self, context, vnf_instance, vnf_dict,
|
||||
@ -351,10 +341,6 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
self._instantiate_vnf(context, vnf_instance, vnf_dict,
|
||||
vim_connection_info, instantiate_vnf_req)
|
||||
|
||||
self._vnf_instance_update(context, vnf_instance,
|
||||
instantiation_state=fields.VnfInstanceState.INSTANTIATED,
|
||||
task_state=None)
|
||||
|
||||
@log.log
|
||||
@revert_to_error_task_state
|
||||
def terminate_vnf(self, context, vnf_instance, terminate_vnf_req):
|
||||
@ -929,7 +915,12 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
LOG.debug(
|
||||
"is_reverse: %s",
|
||||
scale_vnf_request.additional_params.get('is_reverse'))
|
||||
if scale_vnf_request.additional_params['is_reverse'] == 'True':
|
||||
scale_json = vnf_info['attributes']['scale_group']
|
||||
scaleGroupDict = jsonutils.loads(scale_json)
|
||||
key_aspect = scale_vnf_request.aspect_id
|
||||
default = scaleGroupDict['scaleGroupDict'][key_aspect]['default']
|
||||
if (scale_vnf_request.type == 'SCALE_IN' and
|
||||
scale_vnf_request.additional_params['is_reverse'] == 'True'):
|
||||
self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'scale_in_reverse',
|
||||
@ -944,7 +935,27 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
)
|
||||
self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'scale_in_reverse_wait',
|
||||
'scale_update_wait',
|
||||
plugin=self,
|
||||
context=context,
|
||||
auth_attr=vim_connection_info.access_info,
|
||||
vnf_info=vnf_info,
|
||||
region_name=vim_connection_info.access_info.get('region_name')
|
||||
)
|
||||
elif scale_vnf_request.type == 'SCALE_OUT' and default == 0:
|
||||
self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'scale_out_initial',
|
||||
plugin=self,
|
||||
context=context,
|
||||
auth_attr=vim_connection_info.access_info,
|
||||
vnf_info=vnf_info,
|
||||
scale_vnf_request=scale_vnf_request,
|
||||
region_name=vim_connection_info.access_info.get('region_name')
|
||||
)
|
||||
self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'scale_update_wait',
|
||||
plugin=self,
|
||||
context=context,
|
||||
auth_attr=vim_connection_info.access_info,
|
||||
|
@ -1350,10 +1350,32 @@ class Kubernetes(abstract_driver.VnfAbstractDriver,
|
||||
grp_id):
|
||||
pass
|
||||
|
||||
def scale_in_reverse_wait(self,
|
||||
def scale_out_initial(self,
|
||||
context,
|
||||
plugin,
|
||||
auth_attr,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
region_name):
|
||||
pass
|
||||
|
||||
def scale_update_wait(self,
|
||||
context,
|
||||
plugin,
|
||||
auth_attr,
|
||||
vnf_info,
|
||||
region_name):
|
||||
pass
|
||||
|
||||
def get_cinder_list(self,
|
||||
vnf_info):
|
||||
pass
|
||||
|
||||
def get_grant_resource(self,
|
||||
vnf_instance,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
placement_obj_list,
|
||||
vim_connection_info,
|
||||
del_list):
|
||||
pass
|
||||
|
@ -34,10 +34,12 @@ from tacker._i18n import _
|
||||
from tacker.common import exceptions
|
||||
from tacker.common import log
|
||||
from tacker.common import utils
|
||||
from tacker.db.common_services import common_services_db_plugin
|
||||
from tacker.extensions import vnflcm
|
||||
from tacker.extensions import vnfm
|
||||
from tacker import objects
|
||||
from tacker.objects import fields
|
||||
from tacker.plugins.common import constants
|
||||
from tacker.tosca.utils import represent_odict
|
||||
from tacker.vnflcm import utils as vnflcm_utils
|
||||
from tacker.vnfm.infra_drivers import abstract_driver
|
||||
@ -52,6 +54,11 @@ from tacker.vnfm.lcm_user_data.constants import USER_DATA_TIMEOUT
|
||||
|
||||
eventlet.monkey_patch(time=True)
|
||||
|
||||
SCALING_GROUP_RESOURCE = "OS::Heat::AutoScalingGroup"
|
||||
NOVA_SERVER_RESOURCE = "OS::Nova::Server"
|
||||
|
||||
VNF_PACKAGE_HOT_DIR = 'Files'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
@ -108,6 +115,9 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
self.STACK_RETRY_WAIT = cfg.CONF.openstack_vim.stack_retry_wait
|
||||
self.IMAGE_RETRIES = 10
|
||||
self.IMAGE_RETRY_WAIT = 10
|
||||
self.LOCK_RETRIES = 10
|
||||
self.LOCK_RETRY_WAIT = 10
|
||||
self._cos_db_plg = common_services_db_plugin.CommonServicesPluginDb()
|
||||
|
||||
def get_type(self):
|
||||
return 'openstack'
|
||||
@ -124,7 +134,17 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
inst_req_info=None, grant_info=None,
|
||||
vnf_instance=None):
|
||||
LOG.debug('vnf %s', vnf)
|
||||
region_name = vnf.get('placement_attr', {}).get('region_name', None)
|
||||
if vnf.get('grant'):
|
||||
if vnf['grant'].vim_connections:
|
||||
vim_con = vnf['grant'].vim_connections[0]
|
||||
auth_attr = vim_con.access_info
|
||||
region_name = auth_attr.get('region')
|
||||
else:
|
||||
region_name = vnf.get('placement_attr', {}).\
|
||||
get('region_name', None)
|
||||
else:
|
||||
region_name = vnf.get('placement_attr', {}).\
|
||||
get('region_name', None)
|
||||
heatclient = hc.HeatClient(auth_attr, region_name)
|
||||
additional_param = None
|
||||
if inst_req_info is not None:
|
||||
@ -157,7 +177,8 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
for name, hot in nested_hot_dict.items():
|
||||
vnf['attributes'][name] = self._format_base_hot(hot)
|
||||
|
||||
vnfd_str = vnf['vnfd']['attributes']['vnfd']
|
||||
vnfd_str = vnf['vnfd']['attributes']['vnfd_' +
|
||||
inst_req_info.flavour_id]
|
||||
vnfd_dict = yaml.safe_load(vnfd_str)
|
||||
LOG.debug('VNFD: %s', vnfd_dict)
|
||||
LOG.debug('VNF package path: %s', vnf_package_path)
|
||||
@ -220,6 +241,30 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
for name, value in scaleGroupDict['scaleGroupDict'].items():
|
||||
hot_param_dict[name + '_desired_capacity'] = \
|
||||
value['default']
|
||||
if vnf.get('grant'):
|
||||
grant = vnf['grant']
|
||||
ins_inf = vnf_instance.instantiated_vnf_info.vnfc_resource_info
|
||||
for addrsc in grant.add_resources:
|
||||
for zone in grant.zones:
|
||||
if zone.id == addrsc.zone_id:
|
||||
vdu_name = None
|
||||
for rsc in ins_inf:
|
||||
if addrsc.resource_definition_id == rsc.id:
|
||||
vdu_name = rsc.vdu_id
|
||||
break
|
||||
if not vdu_name:
|
||||
continue
|
||||
hot_param_dict['nfv']['VDU'][vdu_name]['zone'] = \
|
||||
zone.zone_id
|
||||
if 'vim_assets' in grant and grant.vim_assets:
|
||||
for flavour in grant.vim_assets.compute_resource_flavours:
|
||||
vdu_name = flavour.vnfd_virtual_compute_desc_id
|
||||
hot_param_dict['nfv']['VDU'][vdu_name]['flavor'] = \
|
||||
flavour.vim_flavour_id
|
||||
for image in grant.vim_assets.software_images:
|
||||
vdu_name = image.vnfd_software_image_id
|
||||
hot_param_dict['nfv']['VDU'][vdu_name]['image'] = \
|
||||
image.vim_software_image_id
|
||||
|
||||
# Add stack param to vnf_attributes
|
||||
vnf['attributes'].update({'stack_param': str(hot_param_dict)})
|
||||
@ -1482,15 +1527,63 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
mark_unhealthy=True,
|
||||
resource_status_reason='Scale')
|
||||
paramDict = {}
|
||||
paramDict[scale_vnf_request.aspect_id +
|
||||
'_desired_capacity'] = vnf_info['res_num']
|
||||
scale_json = vnf_info['attributes']['scale_group']
|
||||
scaleGroupDict = jsonutils.loads(scale_json)
|
||||
for name, value in scaleGroupDict['scaleGroupDict'].items():
|
||||
paramDict[name + '_desired_capacity'] = value['default']
|
||||
paramDict[scale_vnf_request.aspect_id + '_desired_capacity'] = \
|
||||
vnf_info['res_num']
|
||||
stack_update_param = {
|
||||
'parameters': paramDict,
|
||||
'existing': True}
|
||||
heatclient.update(vnf_info['instance_id'], **stack_update_param)
|
||||
stack_param = jsonutils.loads(vnf_info['attributes']['stack_param'])
|
||||
stack_param.update(paramDict)
|
||||
vnf_info['attributes'].update({'stack_param': str(paramDict)})
|
||||
|
||||
@log.log
|
||||
def scale_in_reverse_wait(
|
||||
def scale_out_initial(self, context, plugin, auth_attr, vnf_info,
|
||||
scale_vnf_request, region_name):
|
||||
scale_json = vnf_info['attributes']['scale_group']
|
||||
scaleGroupDict = jsonutils.loads(scale_json)
|
||||
key_aspect = scale_vnf_request.aspect_id
|
||||
num = scaleGroupDict['scaleGroupDict'][key_aspect]['num']
|
||||
vnf_info['res_num'] = num * scale_vnf_request.number_of_steps
|
||||
heatclient = hc.HeatClient(auth_attr, region_name)
|
||||
paramDict = {}
|
||||
for name, value in scaleGroupDict['scaleGroupDict'].items():
|
||||
paramDict[name + '_desired_capacity'] = value['default']
|
||||
paramDict[scale_vnf_request.aspect_id +
|
||||
'_desired_capacity'] = vnf_info['res_num']
|
||||
stack_param = yaml.safe_load(vnf_info['attributes']['stack_param'])
|
||||
grant = vnf_info['grant']
|
||||
for addrsc in grant.add_resources:
|
||||
for zone in grant.zones:
|
||||
if zone.id == addrsc.zone_id:
|
||||
for rsc in vnf_info['addResources']:
|
||||
if addrsc.id == rsc.id:
|
||||
vdu_name = rsc.vdu_id
|
||||
break
|
||||
stack_param['nfv']['VDU'][vdu_name]['zone'] = zone.zone_id
|
||||
if 'vim_assets' in grant and grant.vim_assets:
|
||||
for flavour in grant.vim_assets.compute_resource_flavours:
|
||||
vdu_name = flavour.vnfd_virtual_compute_desc_id
|
||||
stack_param['nfv']['VDU'][vdu_name]['flavor'] = \
|
||||
flavour.vim_flavour_id
|
||||
for image in grant.vim_assets.software_images:
|
||||
vdu_name = image.vnfd_software_image_id
|
||||
stack_param['nfv']['VDU'][vdu_name]['image'] = \
|
||||
image.vim_software_image_id
|
||||
|
||||
paramDict['nfv'] = stack_param['nfv']
|
||||
stack_update_param = {
|
||||
'parameters': paramDict,
|
||||
'existing': True}
|
||||
heatclient.update(vnf_info['instance_id'], **stack_update_param)
|
||||
vnf_info['attributes'].update({'stack_param': str(paramDict)})
|
||||
|
||||
@log.log
|
||||
def scale_update_wait(
|
||||
self,
|
||||
context,
|
||||
plugin,
|
||||
@ -1501,3 +1594,251 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
|
||||
auth_attr, infra_cnst.STACK_UPDATE_IN_PROGRESS,
|
||||
infra_cnst.STACK_UPDATE_COMPLETE,
|
||||
vnfm.VNFScaleWaitFailed, region_name=region_name)
|
||||
|
||||
def get_cinder_list(self, vnf_info):
|
||||
cinder_list = []
|
||||
block_key = 'block_device_mapping_v2'
|
||||
if not vnf_info['attributes'].get('scale_group'):
|
||||
heat_yaml = vnf_info['attributes']['heat_template']
|
||||
heat_dict = yaml.safe_load(heat_yaml)
|
||||
for resource_name, resource in heat_dict['resources'].items():
|
||||
if resource.get('properties') and resource.get(
|
||||
'properties').get(block_key):
|
||||
for cinder in resource['properties'][block_key]:
|
||||
if cinder['volume_id'].get('get_resource'):
|
||||
cinder_list.append(
|
||||
cinder['volume_id']['get_resource'])
|
||||
else:
|
||||
for resource_name, resource in vnf_info['attributes'].items():
|
||||
if '.yaml' in resource_name:
|
||||
heat_dict = yaml.safe_load(resource)
|
||||
for resource_name, resource in heat_dict['resources'].\
|
||||
items():
|
||||
if resource.get('properties') and resource.get(
|
||||
'properties').get(block_key):
|
||||
for cinder in resource['properties'][block_key]:
|
||||
if cinder['volume_id'].get('get_resource'):
|
||||
cinder_list.append(
|
||||
cinder['volume_id']['get_resource'])
|
||||
return cinder_list
|
||||
|
||||
def get_grant_resource(
|
||||
self,
|
||||
vnf_instance,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
placement_obj_list,
|
||||
vim_connection_info,
|
||||
del_list):
|
||||
if scale_vnf_request.type == 'SCALE_OUT':
|
||||
self._get_grant_resource_scale_out(vnf_info,
|
||||
scale_vnf_request,
|
||||
placement_obj_list)
|
||||
else:
|
||||
self.get_grant_resource_scale_in(vnf_instance,
|
||||
vnf_info,
|
||||
vim_connection_info,
|
||||
del_list)
|
||||
|
||||
def _get_grant_resource_scale_out(
|
||||
self,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
placement_obj_list):
|
||||
add_resources = []
|
||||
affinity_list = []
|
||||
placement_constraint_list = []
|
||||
uuid_list = []
|
||||
port_uuid_list = []
|
||||
storage_uuid_list = []
|
||||
heat_template = vnf_info['attributes']['heat_template']
|
||||
heat_resource = yaml.safe_load(heat_template)
|
||||
key_vnfd = scale_vnf_request.aspect_id + '_scale_out'
|
||||
ajust_prop = heat_resource['resources'][key_vnfd]['properties']
|
||||
ajust = ajust_prop['scaling_adjustment']
|
||||
size = ajust * scale_vnf_request.number_of_steps
|
||||
yaml_name = scale_vnf_request.aspect_id + '_res.yaml'
|
||||
if not vnf_info['attributes'].get(yaml_name):
|
||||
yaml_name = scale_vnf_request.aspect_id + '.hot.yaml'
|
||||
nested_hot = yaml.safe_load(
|
||||
vnf_info['attributes'][yaml_name])
|
||||
for resource_name, resource in nested_hot['resources'].items():
|
||||
if resource['type'] == 'OS::Nova::Server':
|
||||
for i in range(size):
|
||||
add_uuid = uuidutils.generate_uuid()
|
||||
rsc = objects.ResourceDefinition(
|
||||
id=add_uuid,
|
||||
type=constants.TYPE_COMPUTE,
|
||||
vdu_id=resource_name,
|
||||
resource_template_id=resource_name)
|
||||
add_resources.append(rsc)
|
||||
uuid_list.append(add_uuid)
|
||||
for net in resource.get('networks', []):
|
||||
add_uuid = uuidutils.generate_uuid()
|
||||
port_rsc = net['port']['get_resource']
|
||||
rsc = objects.ResourceDefinition(
|
||||
id=add_uuid,
|
||||
type=constants.TYPE_LINKPORT,
|
||||
vdu_id=resource_name,
|
||||
resource_template_id=port_rsc)
|
||||
add_resources.append(rsc)
|
||||
port_uuid_list.append(add_uuid)
|
||||
if resource['properties'].get('block_device_mapping_v2'):
|
||||
for i in range(size):
|
||||
for cinder in resource['properties'].get(
|
||||
'block_device_mapping_v2', []):
|
||||
add_uuid = uuidutils.generate_uuid()
|
||||
vol_rsc = cinder['volume_id']['get_resource']
|
||||
rsc = objects.ResourceDefinition(
|
||||
id=add_uuid,
|
||||
type=constants.TYPE_STORAGE,
|
||||
vdu_id=resource_name,
|
||||
resource_template_id=vol_rsc)
|
||||
add_resources.append(rsc)
|
||||
storage_uuid_list.append(add_uuid)
|
||||
if resource['properties'].get('scheduler_hints'):
|
||||
sch_hint = resource['properties']['scheduler_hints']
|
||||
if sch_hint['group'].get('get_param'):
|
||||
affinity_name = sch_hint['group']['get_param']
|
||||
else:
|
||||
affinity_name = sch_hint['group']['get_resource']
|
||||
for placement in placement_obj_list:
|
||||
if placement.server_group_name == affinity_name:
|
||||
for uuid in uuid_list:
|
||||
rsc = objects.ConstraintResourceRef(
|
||||
id_type='GRANT', resource_id=uuid)
|
||||
plm = jsonutils.loads(placement.resource)
|
||||
plm.append(rsc.to_dict())
|
||||
placement.resource = jsonutils.dumps(plm)
|
||||
affinity_list.append(affinity_name)
|
||||
break
|
||||
if resource['type'] == 'OS::Cinder::VolumeAttachment':
|
||||
for i in range(size):
|
||||
add_uuid = uuidutils.generate_uuid()
|
||||
vol_rsc = resource['properties']['instance_uuid']
|
||||
rsc = objects.ResourceDefinition(
|
||||
id=add_uuid,
|
||||
type=constants.TYPE_STORAGE,
|
||||
vdu_id=vol_rsc['get_resource'],
|
||||
resource_template_id=resource_name)
|
||||
add_resources.append(rsc)
|
||||
storage_uuid_list.append(add_uuid)
|
||||
vnf_info['uuid_list'] = uuid_list
|
||||
vnf_info['port_uuid_list'] = port_uuid_list
|
||||
vnf_info['storage_uuid_list'] = storage_uuid_list
|
||||
for placement in placement_obj_list:
|
||||
if placement.server_group_name in affinity_list:
|
||||
plm = jsonutils.loads(placement.resource)
|
||||
addRsc = []
|
||||
for pl in plm:
|
||||
vim_id = pl.get('vim_connection_id')
|
||||
addRsc.append(
|
||||
objects.ConstraintResourceRef(
|
||||
id_type=pl['id_type'],
|
||||
resource_id=pl['resource_id'],
|
||||
vim_connection_id=vim_id))
|
||||
placement_constraint = objects.PlacementConstraint(
|
||||
affinity_or_anti_affinity='ANTI_AFFINITY',
|
||||
scope='ZONE',
|
||||
resource=addRsc,
|
||||
fallback_best_effort=True)
|
||||
placement_constraint_list.append(placement_constraint)
|
||||
vnf_info['addResources'] = add_resources
|
||||
vnf_info['removeResources'] = []
|
||||
vnf_info['affinity_list'] = affinity_list
|
||||
vnf_info['placement_constraint_list'] = placement_constraint_list
|
||||
|
||||
def get_grant_resource_scale_in(
|
||||
self,
|
||||
vnf_instance,
|
||||
vnf_info,
|
||||
vim_connection_info,
|
||||
del_list):
|
||||
remove_resources = []
|
||||
access_info = vim_connection_info.access_info
|
||||
|
||||
heatclient = hc.HeatClient(access_info,
|
||||
region_name=access_info.get('region'))
|
||||
inst_info = vnf_instance.instantiated_vnf_info
|
||||
for del_rsc in del_list:
|
||||
scale_resurce_list = heatclient.resource_get_list(del_rsc)
|
||||
for rsc in scale_resurce_list:
|
||||
if rsc.resource_type == 'OS::Nova::Server':
|
||||
for vnfc_resource in inst_info.vnfc_resource_info:
|
||||
if vnfc_resource.\
|
||||
compute_resource.resource_id == \
|
||||
rsc.physical_resource_id:
|
||||
cmo_rsc = vnfc_resource.compute_resource
|
||||
vim_id = cmo_rsc.vim_connection_id
|
||||
rsc_id = cmo_rsc.resource_id
|
||||
resource = objects.ResourceDefinition(
|
||||
id=vnfc_resource.id,
|
||||
type=constants.TYPE_COMPUTE,
|
||||
vdu_id=vnfc_resource.vdu_id,
|
||||
resource_template_id=vnfc_resource.vdu_id,
|
||||
resource=objects.ResourceHandle(
|
||||
vim_connection_id=vim_id,
|
||||
resource_id=rsc_id))
|
||||
remove_resources.append(resource)
|
||||
if rsc.resource_type == 'OS::Neutron::Port':
|
||||
for vl_resource in \
|
||||
inst_info.vnf_virtual_link_resource_info:
|
||||
for cp_resource in vl_resource.vnf_link_ports:
|
||||
cp_handl = cp_resource.resource_handle
|
||||
cp_id = cp_handl.resource_id
|
||||
vim_id = cp_handl.vim_connection_id
|
||||
if cp_id == rsc.physical_resource_id:
|
||||
for vnfc_resource in inst_info.\
|
||||
vnfc_resource_info:
|
||||
for vnfc_cp_rsc in vnfc_resource.\
|
||||
vnfc_cp_info:
|
||||
if cp_resource.\
|
||||
cp_instance_id == \
|
||||
vnfc_cp_rsc.id:
|
||||
p_id = cp_resource.id
|
||||
v_id = vnfc_resource.vdu_id
|
||||
d_id = vnfc_cp_rsc.cpd_id
|
||||
r_hd = objects.\
|
||||
ResourceHandle()
|
||||
r_hd.\
|
||||
vim_connection_id = \
|
||||
vim_id
|
||||
r_hd.resource_id = cp_id
|
||||
rs = objects.\
|
||||
ResourceDefinition()
|
||||
rs.id = p_id
|
||||
rs.type = 'constants.\
|
||||
TYPE_LINKPORT'
|
||||
rs.vdu_id = v_id
|
||||
rs.resource_template_id = d_id
|
||||
rs.resource = r_hd
|
||||
remove_resources.append(
|
||||
rs)
|
||||
if rsc.resource_type == 'OS::Cinder::Volume':
|
||||
st_info = inst_info.virtual_storage_resource_info
|
||||
for storage_resource in st_info:
|
||||
st_rsc = storage_resource.storage_resource
|
||||
st_id = st_rsc.resource_id
|
||||
if st_id == rsc.physical_resource_id:
|
||||
ins_vnfc = inst_info.vnfc_resource_info
|
||||
for vnfc_resource in ins_vnfc:
|
||||
s_ids = vnfc_resource.storage_resource_ids
|
||||
if storage_resource.id in s_ids:
|
||||
rs = objects.ResourceDefinition()
|
||||
rs.id = storage_resource.id
|
||||
rs.type = 'STORAGE'
|
||||
rs.vdu_id = vnfc_resource.vdu_id
|
||||
tmp_id = storage_resource.\
|
||||
virtual_storage_desc_id
|
||||
rs.resource_template_id = tmp_id
|
||||
r_hd = objects.ResourceHandle()
|
||||
vim_id = st_rsc.vim_connection_id
|
||||
rsc_id = st_rsc.resource_id
|
||||
r_hd.vim_connection_id = vim_id
|
||||
r_hd.resource_id = rsc_id
|
||||
rs.resource = r_hd
|
||||
remove_resources.append(rs)
|
||||
vnf_info['addResources'] = []
|
||||
vnf_info['removeResources'] = remove_resources
|
||||
vnf_info['affinity_list'] = []
|
||||
vnf_info['placement_constraint_list'] = []
|
||||
|
@ -80,10 +80,35 @@ class VnfScaleAbstractDriver(extensions.PluginInterface):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def scale_in_reverse_wait(self,
|
||||
def scale_out_initial(self,
|
||||
context,
|
||||
plugin,
|
||||
auth_attr,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
region_name):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def scale_update_wait(self,
|
||||
context,
|
||||
plugin,
|
||||
auth_attr,
|
||||
vnf_info,
|
||||
region_name):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_cinder_list(self,
|
||||
vnf_info):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_grant_resource(self,
|
||||
vnf_instance,
|
||||
vnf_info,
|
||||
scale_vnf_request,
|
||||
placement_obj_list,
|
||||
vim_connection_info,
|
||||
del_list):
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user