def post_heal_vnf(self, context, vnf_instance, vim_connection_info, heal_vnf_request): """Update resource_id for each vnfc resources :param context: A RequestContext :param vnf_instance: tacker.objects.VnfInstance to be healed :vim_info: Credentials to initialize Vim connection :heal_vnf_request: tacker.objects.HealVnfRequest object containing parameters passed in the heal request """ access_info = vim_connection_info.access_info region_name = access_info.get('region') heatclient = hc.HeatClient(access_info, region_name) inst_vnf_info = vnf_instance.instantiated_vnf_info stack_resources = self._get_stack_resources(inst_vnf_info.instance_id, heatclient) vnfc_resources = self._get_vnfc_resources_from_heal_request( inst_vnf_info, heal_vnf_request) for vnfc_res_info in vnfc_resources: stack_id = vnfc_res_info.metadata.get("stack_id") resources = stack_resources.get(stack_id) if not resources: # NOTE(tpatil): This could happen when heat child stacks # and the stack_id stored in metadata of vnfc_res_info are # not in sync. There is no point in syncing inconsistent # resources information so exit with an error, error = "Failed to find stack_id %s" % stack_id raise exceptions.VnfHealFailed(id=vnf_instance.id, error=error) self._update_vnfc_resource_info(vnf_instance, vnfc_res_info, {stack_id: resources}, update_network_resource=False)
def update(self, plugin, context, vnf_id, vnf_dict, vnf, auth_attr): region_name = vnf_dict.get('placement_attr', {}).get('region_name', None) heatclient = hc.HeatClient(auth_attr, region_name) heatclient.get(vnf_id) # update config attribute config_yaml = vnf_dict.get('attributes', {}).get('config', '') update_yaml = vnf['vnf'].get('attributes', {}).get('config', '') LOG.debug('yaml orig %(orig)s update %(update)s', { 'orig': config_yaml, 'update': update_yaml }) # If config_yaml is None, yaml.safe_load() will raise Attribute Error. # So set config_yaml to {}, if it is None. if not config_yaml: config_dict = {} else: config_dict = yaml.safe_load(config_yaml) or {} update_dict = yaml.safe_load(update_yaml) if not update_dict: return LOG.debug('dict orig %(orig)s update %(update)s', { 'orig': config_dict, 'update': update_dict }) utils.deep_update(config_dict, update_dict) LOG.debug('dict new %(new)s update %(update)s', { 'new': config_dict, 'update': update_dict }) new_yaml = yaml.safe_dump(config_dict) vnf_dict.setdefault('attributes', {})['config'] = new_yaml
def _wait_until_stack_ready(self, vnf_id, auth_attr, wait_status, region_name=None): heatclient = hc.HeatClient(auth_attr, region_name) stack = heatclient.get(vnf_id) status = stack.stack_status stack_retries = self.STACK_RETRIES while status == wait_status and stack_retries > 0: time.sleep(self.STACK_RETRY_WAIT) try: stack = heatclient.get(vnf_id) except Exception: LOG.warning( "VNF Instance setup may not have " "happened because Heat API request failed " "while waiting for the stack %(stack)s to be " "created", {'stack': vnf_id}) # continue to avoid temporary connection error to target # VIM status = stack.stack_status LOG.debug('status: %s', status) stack_retries = stack_retries - 1 LOG.debug('stack status: %(stack)s %(status)s', { 'stack': str(stack), 'status': status }) return stack, status, stack_retries
def _delete_heat_stack(vim_auth): placement_attr = vnf_dict.get('placement_attr', {}) region_name = placement_attr.get('region_name') heatclient = hc.HeatClient(auth_attr=vim_auth, region_name=region_name) heatclient.delete(vnf_dict['instance_id']) LOG.debug("Heat stack %s delete initiated", vnf_dict['instance_id']) _log_monitor_events(context, vnf_dict, "ActionRespawnHeat invoked")
def update_wait(self, plugin, context, vnf_id, auth_attr, region_name=None): # do nothing but checking if the stack exists at the moment heatclient = hc.HeatClient(auth_attr, region_name) heatclient.get(vnf_id)
def update_wait(self, plugin, context, vnf_dict, auth_attr, region_name=None): # do nothing but checking if the stack exists at the moment heatclient = hc.HeatClient(auth_attr, region_name) stack = heatclient.get(vnf_dict['instance_id']) mgmt_ips = self._find_mgmt_ips(stack.outputs) if mgmt_ips: vnf_dict['mgmt_ip_address'] = jsonutils.dump_as_bytes(mgmt_ips)
def create(self, plugin, context, vnf, auth_attr): LOG.debug('vnf %s', vnf) region_name = vnf.get('placement_attr', {}).get('region_name', None) heatclient = hc.HeatClient(auth_attr, region_name) tth = translate_template.TOSCAToHOT(vnf, heatclient) tth.generate_hot() stack = self._create_stack(heatclient, tth.vnf, tth.fields) return stack['stack']['id']
def post_vnf_instantiation(self, context, vnf_instance, vim_connection_info): inst_vnf_info = vnf_instance.instantiated_vnf_info access_info = vim_connection_info.access_info heatclient = hc.HeatClient(access_info, region_name=access_info.get('region')) stack_resources = self._get_stack_resources(inst_vnf_info.instance_id, heatclient) self._update_vnfc_resources(vnf_instance, stack_resources)
def scale(self, context, plugin, auth_attr, policy, region_name): heatclient = hc.HeatClient(auth_attr, region_name) policy_rsc = get_scaling_policy_name(policy_name=policy['name'], action=policy['action']) events = heatclient.resource_event_list(policy['instance_id'], policy_rsc, limit=1, sort_dir='desc', sort_keys='event_time') heatclient.resource_signal(policy['instance_id'], policy_rsc) return events[0].id
def __init__(self, context, vnf_dict, heal_request_data_obj): super(Vdu, self).__init__() self.context = context self.vnf_dict = vnf_dict self.heal_request_data_obj = heal_request_data_obj vim_id = self.vnf_dict['vim_id'] vim_res = vim_client.VimClient().get_vim(context, vim_id) placement_attr = vnf_dict.get('placement_attr', {}) auth_attr = vim_res['vim_auth'] region_name = placement_attr.get('region_name', None) self.heat_client = hc.HeatClient(auth_attr=auth_attr, region_name=region_name)
def _wait_until_stack_ready(self, vnf_id, auth_attr, wait_status, expected_status, exception_class, region_name=None): heatclient = hc.HeatClient(auth_attr, region_name) stack_retries = self.STACK_RETRIES status = wait_status stack = None while stack_retries > 0: try: stack_retries = stack_retries - 1 stack = heatclient.get(vnf_id) status = stack.stack_status if status == expected_status: LOG.debug('stack status: %(stack)s %(status)s', { 'stack': str(stack), 'status': status }) return stack time.sleep(self.STACK_RETRY_WAIT) LOG.debug('status: %s', status) except Exception: LOG.warning( "VNF Instance setup may not have " "happened because Heat API request failed " "while waiting for the stack %(stack)s to be " "created", {'stack': vnf_id}) # continue to avoid temporary connection error to target # VIM if stack_retries == 0 and status != expected_status: error_reason = _("action is not completed within {wait} " "seconds on stack {stack}").format( wait=(self.STACK_RETRIES * self.STACK_RETRY_WAIT), stack=vnf_id) raise exception_class(reason=error_reason) elif stack_retries != 0 and status != wait_status: if stack: error_reason = stack.stack_status_reason else: error_reason = _("action on VNF %(vnf_id)s is not " "completed. Current status of stack is " "%(stack_status)s") % { 'vnf_id': vnf_id, 'stack_status': status } LOG.warning(error_reason) raise exception_class(reason=error_reason)
def delete_wait(self, plugin, context, vnf_id, auth_attr, region_name=None): heatclient = hc.HeatClient(auth_attr, region_name) stack = heatclient.get(vnf_id) status = stack.stack_status error_reason = None stack_retries = self.STACK_RETRIES while (status == 'DELETE_IN_PROGRESS' and stack_retries > 0): time.sleep(self.STACK_RETRY_WAIT) try: stack = heatclient.get(vnf_id) except heatException.HTTPNotFound: return except Exception: LOG.warning( "VNF Instance cleanup may not have " "happened because Heat API request failed " "while waiting for the stack %(stack)s to be " "deleted", {'stack': vnf_id}) # Just like create wait, ignore the exception to # avoid temporary connection error. status = stack.stack_status stack_retries = stack_retries - 1 if stack_retries == 0 and status != 'DELETE_COMPLETE': error_reason = _("Resource cleanup for vnf is" " not completed within {wait} seconds as " "deletion of Stack {stack} is " "not completed").format( stack=vnf_id, wait=(self.STACK_RETRIES * self.STACK_RETRY_WAIT)) LOG.warning(error_reason) raise vnfm.VNFDeleteWaitFailed(reason=error_reason) if stack_retries != 0 and status != 'DELETE_COMPLETE': error_reason = _("vnf {vnf_id} deletion is not completed. " "{stack_status}").format(vnf_id=vnf_id, stack_status=status) LOG.warning(error_reason) raise vnfm.VNFDeleteWaitFailed(reason=error_reason)
def get_resource_info(self, plugin, context, vnf_info, auth_attr, region_name=None): instance_id = vnf_info['instance_id'] heatclient = hc.HeatClient(auth_attr, region_name) try: # nested_depth=2 is used to get VDU resources # in case of nested template resources_ids =\ heatclient.resource_get_list(instance_id, nested_depth=2) details_dict = {resource.resource_name: {"id": resource.physical_resource_id, "type": resource.resource_type} for resource in resources_ids} return details_dict # Raise exception when Heat API service is not available except Exception: raise vnfm.InfraDriverUnreachable(service="Heat API service")
def update(self, plugin, context, vnf_id, vnf_dict, vnf, auth_attr): region_name = vnf_dict.get('placement_attr', {}).get('region_name', None) heatclient = hc.HeatClient(auth_attr, region_name) heatclient.get(vnf_id) # update config attribute config_yaml = vnf_dict.get('attributes', {}).get('config', '') update_yaml = vnf['vnf'].get('attributes', {}).get('config', '') LOG.debug('yaml orig %(orig)s update %(update)s', { 'orig': config_yaml, 'update': update_yaml }) # If config_yaml is None, yaml.safe_load() will raise Attribute Error. # So set config_yaml to {}, if it is None. if not config_yaml: config_dict = {} else: config_dict = yaml.safe_load(config_yaml) or {} update_dict = yaml.safe_load(update_yaml) if not update_dict: return @log.log def deep_update(orig_dict, new_dict): for key, value in new_dict.items(): if isinstance(value, dict): if key in orig_dict and isinstance(orig_dict[key], dict): deep_update(orig_dict[key], value) continue orig_dict[key] = value LOG.debug('dict orig %(orig)s update %(update)s', { 'orig': config_dict, 'update': update_dict }) deep_update(config_dict, update_dict) LOG.debug('dict new %(new)s update %(update)s', { 'new': config_dict, 'update': update_dict }) new_yaml = yaml.safe_dump(config_dict) vnf_dict.setdefault('attributes', {})['config'] = new_yaml
def create_wait(self, plugin, context, vnf_dict, vnf_id, auth_attr): region_name = vnf_dict.get('placement_attr', {}).get( 'region_name', None) heatclient = hc.HeatClient(auth_attr, region_name) stack = self._wait_until_stack_ready( vnf_id, auth_attr, infra_cnst.STACK_CREATE_IN_PROGRESS, infra_cnst.STACK_CREATE_COMPLETE, vnfm.VNFCreateWaitFailed, region_name=region_name) # scaling enabled if vnf_dict['attributes'].get('scaling_group_names'): group_names = jsonutils.loads( vnf_dict['attributes'].get('scaling_group_names')).values() mgmt_ips = self._find_mgmt_ips_from_groups(heatclient, vnf_id, group_names) else: mgmt_ips = self._find_mgmt_ips(stack.outputs) if mgmt_ips: vnf_dict['mgmt_ip_address'] = jsonutils.dump_as_bytes(mgmt_ips)
def get_connection_points(vnf_dict, vim_id): instance_id = vnf_dict['instance_id'] placement_attr = vnf_dict.get('placement_attr', {}) region_name = placement_attr.get('region_name') vim_res = _fetch_vim(vim_id) try: heatclient = hc.HeatClient(auth_attr=vim_res['vim_auth'], region_name=region_name) resources_ids = heatclient.resource_get_list(instance_id, nested_depth=2) vnf_details = {resource.resource_name: {"id": resource.physical_resource_id, "type": resource.resource_type} for resource in resources_ids} cp_dict = {} for name, info in vnf_details.items(): if info.get('type') == 'OS::Neutron::Port': cp_dict[name] = info.get('id') LOG.info('log: cp_dict : %s', cp_dict) ### except Exception: LOG.exception('failed to call heat API') return 'FAILED' return cp_dict
def create_wait(self, plugin, context, vnf_dict, vnf_id, auth_attr): region_name = vnf_dict.get('placement_attr', {}).get('region_name', None) heatclient = hc.HeatClient(auth_attr, region_name) stack, status, stack_retries = self._wait_until_stack_ready( vnf_id, auth_attr, infra_cnst.STACK_CREATE_IN_PROGRESS, region_name=region_name) if stack_retries == 0 and status != infra_cnst.STACK_CREATE_COMPLETE: error_reason = _("Resource creation is not completed within" " {wait} seconds as creation of stack {stack}" " is not completed").format( wait=(self.STACK_RETRIES * self.STACK_RETRY_WAIT), stack=vnf_id) LOG.warning("VNF Creation failed: %(reason)s", {'reason': error_reason}) raise vnfm.VNFCreateWaitFailed(reason=error_reason) elif stack_retries != 0 and status != infra_cnst.STACK_CREATE_COMPLETE: error_reason = stack.stack_status_reason raise vnfm.VNFCreateWaitFailed(reason=error_reason) # scaling enabled if vnf_dict['attributes'].get('scaling_group_names'): group_names = jsonutils.loads( vnf_dict['attributes'].get('scaling_group_names')).values() mgmt_ips = self._find_mgmt_ips_from_groups(heatclient, vnf_id, group_names) else: mgmt_ips = self._find_mgmt_ips(stack.outputs) if mgmt_ips: vnf_dict['mgmt_ip_address'] = jsonutils.dump_as_bytes(mgmt_ips)
def heal_vnf(self, context, vnf_instance, vim_connection_info, heal_vnf_request): access_info = vim_connection_info.access_info region_name = access_info.get('region') inst_vnf_info = vnf_instance.instantiated_vnf_info heatclient = hc.HeatClient(access_info, region_name=region_name) def _get_storage_resources(vnfc_resource): # Prepare list of storage resources to be marked unhealthy for storage_id in vnfc_resource.storage_resource_ids: for storage_res_info in inst_vnf_info. \ virtual_storage_resource_info: if storage_res_info.id == storage_id: yield storage_res_info.virtual_storage_desc_id, \ storage_res_info.storage_resource.resource_id def _get_vdu_resources(vnfc_resources): # Prepare list of vdu resources to be marked unhealthy vdu_resources = [] for vnfc_resource in vnfc_resources: resource_details = { "resource_name": vnfc_resource.vdu_id, "physical_resource_id": vnfc_resource.compute_resource.resource_id } vdu_resources.append(resource_details) # Get storage resources for resource_name, resource_id in \ _get_storage_resources(vnfc_resource): resource_details = { "resource_name": resource_name, "physical_resource_id": resource_id } vdu_resources.append(resource_details) return vdu_resources def _prepare_stack_resources_for_updation(vdu_resources, stack_resources): for resource in vdu_resources: for stack_uuid, resources in stack_resources.items(): res_details = resources.get(resource['resource_name']) if (res_details and res_details['physical_resource_id'] == resource['physical_resource_id']): yield stack_uuid, resource['resource_name'] def _resource_mark_unhealthy(): vnfc_resources = self._get_vnfc_resources_from_heal_request( inst_vnf_info, heal_vnf_request) vdu_resources = _get_vdu_resources(vnfc_resources) stack_resources = self._get_stack_resources( inst_vnf_info.instance_id, heatclient) cause = heal_vnf_request.cause or "Healing" for stack_uuid, resource_name in \ _prepare_stack_resources_for_updation( vdu_resources, stack_resources): try: LOG.info( "Marking resource %(resource)s as unhealthy for " "stack %(stack)s for vnf instance %(id)s", { "resource": resource_name, "stack": stack_uuid, "id": vnf_instance.id }) heatclient.resource_mark_unhealthy( stack_id=stack_uuid, resource_name=resource_name, mark_unhealthy=True, resource_status_reason=cause) except Exception as exp: msg = ("Failed to mark stack '%(stack_id)s' resource as " "unhealthy for resource '%(resource)s', " "Error: %(error)s") raise exceptions.VnfHealFailed( id=vnf_instance.id, error=msg % { "stack_id": inst_vnf_info.instance_id, "resource": resource_name, "error": str(exp) }) def _get_stack_status(): stack_statuses = ["CREATE_COMPLETE", "UPDATE_COMPLETE"] stack = heatclient.get(inst_vnf_info.instance_id) if stack.stack_status not in stack_statuses: error = ("Healing of vnf instance %(id)s is possible only " "when stack %(stack_id)s status is %(statuses)s, " "current stack status is %(status)s") raise exceptions.VnfHealFailed( id=vnf_instance.id, error=error % { "id": vnf_instance.id, "stack_id": inst_vnf_info.instance_id, "statuses": ",".join(stack_statuses), "status": stack.stack_status }) _get_stack_status() _resource_mark_unhealthy() LOG.info("Updating stack %(stack)s for vnf instance %(id)s", { "stack": inst_vnf_info.instance_id, "id": vnf_instance.id }) heatclient.update(stack_id=inst_vnf_info.instance_id, existing=True)
def scale_wait(self, context, plugin, auth_attr, policy, region_name, last_event_id): heatclient = hc.HeatClient(auth_attr, region_name) # TODO(kanagaraj-manickam) make wait logic into separate utility method # and make use of it here and other actions like create and delete stack_retries = self.STACK_RETRIES while (True): try: time.sleep(self.STACK_RETRY_WAIT) stack_id = policy['instance_id'] policy_name = get_scaling_policy_name( policy_name=policy['name'], action=policy['action']) events = heatclient.resource_event_list(stack_id, policy_name, limit=1, sort_dir='desc', sort_keys='event_time') if events[0].id != last_event_id: if events[0].resource_status == 'SIGNAL_COMPLETE': break except Exception as e: error_reason = _("VNF scaling failed for stack %(stack)s with " "error %(error)s") % { 'stack': policy['instance_id'], 'error': str(e) } LOG.warning(error_reason) raise vnfm.VNFScaleWaitFailed(vnf_id=policy['vnf']['id'], reason=error_reason) if stack_retries == 0: metadata = heatclient.resource_metadata(stack_id, policy_name) if not metadata['scaling_in_progress']: error_reason = _('when signal occurred within cool down ' 'window, no events generated from heat, ' 'so ignore it') LOG.warning(error_reason) break error_reason = _( "VNF scaling failed to complete within %{wait}s seconds " "while waiting for the stack %(stack)s to be " "scaled.") % { 'stack': stack_id, 'wait': self.STACK_RETRIES * self.STACK_RETRY_WAIT } LOG.warning(error_reason) raise vnfm.VNFScaleWaitFailed(vnf_id=policy['vnf']['id'], reason=error_reason) stack_retries -= 1 def _fill_scaling_group_name(): vnf = policy['vnf'] scaling_group_names = vnf['attributes']['scaling_group_names'] policy['group_name'] = jsonutils.loads(scaling_group_names)[ policy['name']] _fill_scaling_group_name() mgmt_ips = self._find_mgmt_ips_from_groups(heatclient, policy['instance_id'], [policy['group_name']]) return jsonutils.dumps(mgmt_ips)
def delete(self, plugin, context, vnf_id, auth_attr, region_name=None): heatclient = hc.HeatClient(auth_attr, region_name) heatclient.delete(vnf_id)
def create_wait(self, plugin, context, vnf_dict, vnf_id, auth_attr): region_name = vnf_dict.get('placement_attr', {}).get('region_name', None) heatclient = hc.HeatClient(auth_attr, region_name) stack = heatclient.get(vnf_id) status = stack.stack_status stack_retries = self.STACK_RETRIES error_reason = None while status == 'CREATE_IN_PROGRESS' and stack_retries > 0: time.sleep(self.STACK_RETRY_WAIT) try: stack = heatclient.get(vnf_id) except Exception: LOG.warning( "VNF Instance setup may not have " "happened because Heat API request failed " "while waiting for the stack %(stack)s to be " "created", {'stack': vnf_id}) # continue to avoid temporary connection error to target # VIM status = stack.stack_status LOG.debug('status: %s', status) stack_retries = stack_retries - 1 LOG.debug('stack status: %(stack)s %(status)s', { 'stack': str(stack), 'status': status }) if stack_retries == 0 and status != 'CREATE_COMPLETE': error_reason = _("Resource creation is not completed within" " {wait} seconds as creation of stack {stack}" " is not completed").format( wait=(self.STACK_RETRIES * self.STACK_RETRY_WAIT), stack=vnf_id) LOG.warning("VNF Creation failed: %(reason)s", {'reason': error_reason}) raise vnfm.VNFCreateWaitFailed(reason=error_reason) elif stack_retries != 0 and status != 'CREATE_COMPLETE': error_reason = stack.stack_status_reason raise vnfm.VNFCreateWaitFailed(reason=error_reason) def _find_mgmt_ips(outputs): LOG.debug('outputs %s', outputs) mgmt_ips = dict( (output['output_key'][len(OUTPUT_PREFIX):], output['output_value']) for output in outputs if output.get('output_key', '').startswith(OUTPUT_PREFIX)) return mgmt_ips # scaling enabled if vnf_dict['attributes'].get('scaling_group_names'): group_names = jsonutils.loads( vnf_dict['attributes'].get('scaling_group_names')).values() mgmt_ips = self._find_mgmt_ips_from_groups(heatclient, vnf_id, group_names) else: mgmt_ips = _find_mgmt_ips(stack.outputs) if mgmt_ips: vnf_dict['mgmt_url'] = jsonutils.dumps(mgmt_ips)
def update(self, plugin, context, vnf_id, vnf_dict, vnf, auth_attr): region_name = vnf_dict.get('placement_attr', {}).get('region_name', None) heatclient = hc.HeatClient(auth_attr, region_name) heatclient.get(vnf_id) update_param_yaml = vnf['vnf'].get('attributes', {}).get('param_values', '') update_config_yaml = vnf['vnf'].get('attributes', {}).get('config', '') if update_param_yaml: # conversion param_values param_yaml = vnf_dict.get('attributes', {}).get('param_values', '') param_dict = yaml.safe_load(param_yaml) update_param_dict = yaml.safe_load(update_param_yaml) # check update values update_values = {} for key, value in update_param_dict.items(): if key not in param_dict or\ update_param_dict[key] != param_dict[key]: update_values[key] = value if not update_values: error_reason = _("at vnf_id {} because all parameters " "match the existing one.").format(vnf_id) LOG.warning(error_reason) raise vnfm.VNFUpdateInvalidInput(reason=error_reason) # update vnf_dict utils.deep_update(param_dict, update_param_dict) new_param_yaml = yaml.safe_dump(param_dict) vnf_dict.setdefault('attributes', {})['param_values'] = new_param_yaml # run stack update stack_update_param = { 'parameters': update_values, 'existing': True } heatclient.update(vnf_id, **stack_update_param) elif not update_param_yaml and not update_config_yaml: error_reason = _("at vnf_id {} because the target " "yaml is empty.").format(vnf_id) LOG.warning(error_reason) raise vnfm.VNFUpdateInvalidInput(reason=error_reason) # update config attribute config_yaml = vnf_dict.get('attributes', {}).get('config', '') LOG.debug('yaml orig %(orig)s update %(update)s', { 'orig': config_yaml, 'update': update_config_yaml }) # If config_yaml is None, yaml.safe_load() will raise Attribute Error. # So set config_yaml to {}, if it is None. if not config_yaml: config_dict = {} else: config_dict = yaml.safe_load(config_yaml) or {} update_dict = yaml.safe_load(update_config_yaml) if not update_dict: return LOG.debug('dict orig %(orig)s update %(update)s', { 'orig': config_dict, 'update': update_dict }) utils.deep_update(config_dict, update_dict) LOG.debug('dict new %(new)s update %(update)s', { 'new': config_dict, 'update': update_dict }) new_yaml = yaml.safe_dump(config_dict) vnf_dict.setdefault('attributes', {})['config'] = new_yaml
def create(self, plugin, context, vnf, auth_attr, base_hot_dict=None, vnf_package_path=None, inst_req_info=None, grant_info=None): LOG.debug('vnf %s', vnf) 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: additional_param = inst_req_info.additional_params user_data_path = None user_data_class = None if additional_param is not None: LOG.debug('additional_param: %s', additional_param) user_data_path = additional_param.get('lcm-operation-user-data') user_data_class = additional_param.get( 'lcm-operation-user-data-class') LOG.debug('UserData path: %s', user_data_path) LOG.debug('UserData class: %s', user_data_class) if user_data_path is not None and user_data_class is not None: LOG.info('Execute user data and create heat-stack.') if base_hot_dict is None: error_reason = _("failed to get Base HOT.") raise vnfm.LCMUserDataFailed(reason=error_reason) vnfd_str = vnf['vnfd']['attributes']['vnfd'] vnfd_dict = yaml.safe_load(vnfd_str) LOG.debug('VNFD: %s', vnfd_dict) LOG.debug('VNF package path: %s', vnf_package_path) sys.path.append(vnf_package_path) user_data_module = os.path.splitext( user_data_path.lstrip('./'))[0].replace('/', '.') LOG.debug('UserData module: %s', user_data_module) LOG.debug('Append sys.path: %s', sys.path) try: module = importlib.import_module(user_data_module) LOG.debug('Append sys.modules: %s', sys.modules) except Exception: self._delete_user_data_module(user_data_module) error_reason = _( "failed to get UserData path based on " "lcm-operation-user-data from additionalParams.") raise vnfm.LCMUserDataFailed(reason=error_reason) finally: sys.path.remove(vnf_package_path) LOG.debug('Remove sys.path: %s', sys.path) try: klass = getattr(module, user_data_class) except Exception: self._delete_user_data_module(user_data_module) error_reason = _( "failed to get UserData class based on " "lcm-operation-user-data-class from additionalParams.") raise vnfm.LCMUserDataFailed(reason=error_reason) # Set the timeout and execute the UserData script. hot_param_dict = None with eventlet.timeout.Timeout(USER_DATA_TIMEOUT, False): try: hot_param_dict = klass.instantiate(base_hot_dict, vnfd_dict, inst_req_info, grant_info) except Exception: raise finally: self._delete_user_data_module(user_data_module) if hot_param_dict is not None: LOG.info('HOT input parameter: %s', hot_param_dict) else: error_reason = _( "fails due to timeout[sec]: %s") % USER_DATA_TIMEOUT raise vnfm.LCMUserDataFailed(reason=error_reason) if not isinstance(hot_param_dict, dict): error_reason = _("return value as HOT parameter from UserData " "is not in dict format.") raise vnfm.LCMUserDataFailed(reason=error_reason) # Create heat-stack with BaseHOT and parameters stack = self._create_stack_with_user_data(heatclient, vnf, base_hot_dict, hot_param_dict) elif user_data_path is None and user_data_class is None: LOG.info('Execute heat-translator and create heat-stack.') tth = translate_template.TOSCAToHOT(vnf, heatclient, inst_req_info, grant_info) tth.generate_hot() stack = self._create_stack(heatclient, tth.vnf, tth.fields) else: error_reason = _( "failed to get lcm-operation-user-data or " "lcm-operation-user-data-class from additionalParams.") raise vnfm.LCMUserDataFailed(reason=error_reason) return stack['stack']['id']