Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 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")
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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']
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
 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)
Ejemplo n.º 11
0
 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)
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
 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")
Ejemplo n.º 14
0
    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
Ejemplo n.º 15
0
    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
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
0
    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)
Ejemplo n.º 20
0
 def delete(self, plugin, context, vnf_id, auth_attr, region_name=None):
     heatclient = hc.HeatClient(auth_attr, region_name)
     heatclient.delete(vnf_id)
Ejemplo n.º 21
0
    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)
Ejemplo n.º 22
0
    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
Ejemplo n.º 23
0
    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']