def _validate_instantiation_levels(policy, instantiation_levels):
    expected_policy_type = [
        'tosca.policies.nfv.VduInstantiationLevels', 'tosca.policies.nfv.'
        'VirtualLinkInstantiationLevels'
    ]
    for policy_name, policy_tpl in policy.items():
        if policy_tpl.get('type') not in expected_policy_type:
            return

        if not instantiation_levels:
            msg = ('Policy of type'
                   ' "tosca.policies.nfv.InstantiationLevels is not defined.')
            raise exceptions.InvalidCSAR(msg)
        if policy_tpl.get('properties'):
            levels_in_policy = policy_tpl.get('properties').get('levels')

            if levels_in_policy:
                invalid_levels = set(
                    levels_in_policy.keys()) - set(instantiation_levels)
            else:
                invalid_levels = set()

            if invalid_levels:
                error_msg = "Level(s) {} not found in defined levels" \
                            " {}".format(",".join(sorted(invalid_levels)),
                                         ",".join(sorted(instantiation_levels)
                                                  ))
                raise exceptions.InvalidCSAR(error_msg)
def _validate_sw_image_data_for_artifact(node_tpl, template_name):
    artifact_type = []
    artifacts = node_tpl.get('artifacts')
    if artifacts:
        for key, value in artifacts.items():
            if value.get('type') == 'tosca.artifacts.nfv.SwImage':
                artifact_type.append(value.get('type'))

        if len(artifact_type) > 1:
            error_msg = ('artifacts of type "tosca.artifacts.nfv.SwImage"'
                         ' is added more than one time for'
                         ' node %(node)s.') % {
                             'node': template_name
                         }
            raise exceptions.InvalidCSAR(error_msg)

        if artifact_type and node_tpl.get('properties'):
            if not node_tpl.get('properties').get('sw_image_data'):
                error_msg = ('Node property "sw_image_data" is missing for'
                             ' artifact type %(type)s for '
                             'node %(node)s.') % {
                                 'type': artifact_type[0],
                                 'node': template_name
                             }
                raise exceptions.InvalidCSAR(error_msg)
Example #3
0
def _validate_sw_image_data_for_artifact(node_tpl, template_name):
    artifact_names = []
    artifacts = node_tpl.get('artifacts')
    if not artifacts:
        return

    for key, value in artifacts.items():
        if isinstance(value, dict):
            if value.get('type') == 'tosca.artifacts.nfv.SwImage':
                artifact_names.append(key)
        elif isinstance(value, str):
            artifact_names.append(key)

    if len(artifact_names) > 1:
        error_msg = ('artifacts of type "tosca.artifacts.nfv.SwImage"'
                     ' is added more than one time for'
                     ' node %(node)s.') % {
                         'node': template_name
                     }
        raise exceptions.InvalidCSAR(error_msg)

    if artifact_names and node_tpl.get('properties'):
        if not node_tpl.get('properties').get('sw_image_data'):
            error_msg = ('Node property "sw_image_data" is missing for'
                         ' artifact %(artifact_name)s for node %(node)s.') % {
                             'artifact_name': artifact_names[0],
                             'node': template_name
                         }
            raise exceptions.InvalidCSAR(error_msg)
Example #4
0
def _get_data_from_csar(tosca, context, id):
    for tp in tosca.nested_tosca_templates_with_topology:
        policies = tp.tpl.get("policies")
        if policies:
            levels = _get_instantiation_levels_from_policy(policies)
            for policy_tpl in policies:
                _validate_instantiation_levels(policy_tpl, levels)

    _validate_sw_image_data_for_artifacts(tosca)
    vnf_data = _get_vnf_data(tosca.nodetemplates)
    if not vnf_data:
        error_msg = "VNF properties are mandatory"
        raise exceptions.InvalidCSAR(error_msg)

    flavours = _populate_flavour_data(tosca)
    if not flavours:
        error_msg = "No VNF flavours are available"
        raise exceptions.InvalidCSAR(error_msg)

    csar = CSAR(tosca.input_path, tosca.a_file)
    vnf_artifacts = []
    if csar.validate():
        vnf_artifacts = _get_vnf_artifacts(csar)

    return vnf_data, flavours, vnf_artifacts
Example #5
0
def _convert_artifacts(vnf_artifacts, artifacts_data, csar):
    artifacts_data_split = re.split(b'\n\n+', artifacts_data)

    for data in artifacts_data_split:
        if re.findall(b'.?Name:.?|.?Source:.?|', data):
            # validate key's existence
            if re.findall(b'.?Algorithm:.?|.?Hash:.?', data):
                artifact_data_dict = yaml.safe_load(data)
                if 'Name' in artifact_data_dict.keys():
                    artifact_data_dict.update(
                        {"Source": artifact_data_dict.pop("Name")})
                if 'Content-Type' in artifact_data_dict.keys():
                    del artifact_data_dict['Content-Type']
                if sorted(ARTIFACT_KEYS) != sorted(artifact_data_dict.keys()):
                    missing_key = list(
                        set(ARTIFACT_KEYS) ^ set(artifact_data_dict.keys()))
                    missing_key = sorted(missing_key)
                    invalid_artifact_err_msg = \
                        (('One of the artifact information '
                          'may not have the key("%(key)s")') %
                         {'key': missing_key})
                    raise exceptions.InvalidCSAR(invalid_artifact_err_msg)
                # validate value's existence
                for key, value in artifact_data_dict.items():
                    if not value:
                        invalid_artifact_err_msg = \
                            (('One of the artifact information may not have '
                              'the key value("%(key)s")') % {'key': key})
                        raise exceptions.InvalidCSAR(invalid_artifact_err_msg)
                artifact_path = artifact_data_dict.get('Source')
                if os.path.splitext(artifact_path)[-1][1:] \
                        in IMAGE_FORMAT_LIST:
                    continue
                else:
                    algorithm = artifact_data_dict.get('Algorithm')
                    hash_code = artifact_data_dict.get('Hash')
                    result = _validate_hash(algorithm, hash_code, csar,
                                            artifact_path)
                    if result:
                        vnf_artifacts.append(artifact_data_dict)
                    else:
                        invalid_artifact_err_msg = \
                            (('The hash "%(hash)s" of artifact file '
                              '"%(artifact)s" is an invalid value.') %
                             {'hash': hash_code, 'artifact': artifact_path})
                        raise exceptions.InvalidCSAR(invalid_artifact_err_msg)

    return vnf_artifacts
def load_csar_data(context, package_uuid, zip_path):

    extract_zip_path = os.path.join(CONF.vnf_package.vnf_package_csar_path,
                                    package_uuid)
    _extract_csar_zip_file(zip_path, extract_zip_path)

    try:
        tosca = ToscaTemplate(zip_path, None, True)
        return _get_data_from_csar(tosca, context, package_uuid)
    except exceptions.InvalidCSAR as exp:
        with excutils.save_and_reraise_exception():
            LOG.error(
                "Error processing CSAR file %(path)s for vnf package"
                " %(uuid)s: Error: %(error)s. ", {
                    'path': zip_path,
                    'uuid': package_uuid,
                    'error': encodeutils.exception_to_unicode(exp)
                })
    except Exception as exp:
        with excutils.save_and_reraise_exception():
            LOG.error(
                "Tosca parser failed for vnf package %(uuid)s: "
                "Error: %(error)s. ", {
                    'uuid': package_uuid,
                    'error': encodeutils.exception_to_unicode(exp)
                })
            exp.reraise = False
            raise exceptions.InvalidCSAR(encodeutils.exception_to_unicode(exp))
Example #7
0
def _get_flavour_data(tp, flavours):
    sw_image_list = []

    # Setting up flavour data
    flavour_id = tp.substitution_mappings.properties.get('flavour_id')
    if flavour_id:
        if isinstance(flavour_id, dict):
            error_msg = "flavour_id should be string and given" \
                        " {}".format(flavour_id)
            raise exceptions.InvalidCSAR(error_msg)
        flavour = {'flavour_id': flavour_id}
    else:
        flavour = {}
    instantiation_levels = _get_instantiation_levels(tp.policies)
    if instantiation_levels:
        flavour.update({'instantiation_levels': instantiation_levels})
    for template_name, node_tpl in tp.tpl.get('node_templates').items():
        # check the flavour property in vnf data
        _update_flavour_data_from_vnf(tp.custom_defs, node_tpl, flavour)

        # Update the software image data
        sw_image = _get_software_image(tp.custom_defs, template_name, node_tpl)
        if sw_image:
            sw_image_list.append(sw_image)

    # Add software images for flavour
    if sw_image_list:
        flavour.update({'sw_images': sw_image_list})

    if flavour:
        flavours.append(flavour)
Example #8
0
def _get_vnf_artifacts(csar):
    vnf_artifacts = []
    if csar.is_tosca_metadata:
        if csar._get_metadata("ETSI-Entry-Manifest"):
            manifest_path = csar._get_metadata("ETSI-Entry-Manifest")
            if manifest_path.lower().endswith(".mf"):
                manifest_data = csar.zfile.read(manifest_path)
                vnf_artifacts = _convert_artifacts(vnf_artifacts,
                                                   manifest_data, csar)
            else:
                invalid_manifest_err_msg = (
                    ('The file "%(manifest)s" in the CSAR "%(csar)s" does not '
                     'contain valid manifest.') % {
                         'manifest': manifest_path,
                         'csar': csar.path
                     })
                raise exceptions.InvalidCSAR(invalid_manifest_err_msg)
        tosca_data = csar.zfile.read(TOSCA_META)
        vnf_artifacts = _convert_artifacts(vnf_artifacts, tosca_data, csar)

    else:
        filelist = csar.zfile.namelist()
        main_template_file_name = os.path.splitext(
            csar.main_template_file_name)[0]
        for path in filelist:
            if path.lower().endswith(".mf"):
                manifest_file_name = os.path.splitext(path)[0]
                if manifest_file_name == main_template_file_name:
                    manifest_data = csar.zfile.read(path)
                    vnf_artifacts = _convert_artifacts(vnf_artifacts,
                                                       manifest_data, csar)
                else:
                    invalid_manifest_err_msg = \
                        (('The filename "%(manifest)s" is an invalid name.'
                          'The name must be the same as the main template '
                          'file name.') %
                        {'manifest': path})
                    raise exceptions.InvalidCSAR(invalid_manifest_err_msg)
    # Deduplication
    vnf_artifacts = [
        dict(t) for t in set([tuple(d.items()) for d in vnf_artifacts])
    ]
    return vnf_artifacts
Example #9
0
def _validate_hash(algorithm, hash_code, csar, artifact_path):
    z = zipfile.ZipFile(csar.path)
    algorithm = algorithm.lower()

    # validate Algorithm's value
    if algorithm in HASH_DICT.keys():
        hash_obj = HASH_DICT[algorithm]()
    else:
        invalid_artifact_err_msg = (('The algorithm("%(algorithm)s") of '
                                     'artifact("%(artifact_path)s") is '
                                     'an invalid value.') % {
                                         'algorithm': algorithm,
                                         'artifact_path': artifact_path
                                     })
        raise exceptions.InvalidCSAR(invalid_artifact_err_msg)
    filelist = csar.zfile.namelist()

    # validate Source's value
    if artifact_path in filelist:
        hash_obj.update(z.read(artifact_path))
    elif ((urlparse(artifact_path).scheme == 'file')
          or (bool(urlparse(artifact_path).scheme)
              and bool(urlparse(artifact_path).netloc))):
        hash_obj.update(urllib2.urlopen(artifact_path).read())
    else:
        invalid_artifact_err_msg = (('The path("%(artifact_path)s") of '
                                     'artifact Source is an invalid value.') %
                                    {
                                        'artifact_path': artifact_path
                                    })
        raise exceptions.InvalidCSAR(invalid_artifact_err_msg)

    # validate Hash's value
    if hash_code == hash_obj.hexdigest():
        return True
    else:
        return False
def _get_instantiation_levels_from_policy(tpl_policies):
    """Get defined instantiation levels

    Getting instantiation levels defined under policy type
    'tosca.policies.nfv.InstantiationLevels'.
    """

    levels = []
    for policy in tpl_policies:
        for key, value in policy.items():
            if value.get('type') == 'tosca.policies.nfv.InstantiationLevels'\
                    and value.get('properties', {}).get('levels', {}):
                levels = value.get('properties').get('levels').keys()
                default_level = value.get('properties').get('default_level')

                if default_level and default_level not in levels:
                    error_msg = "Level {} not found in defined levels" \
                                " {}".format(default_level,
                                             ",".join(sorted(levels)))
                    raise exceptions.InvalidCSAR(error_msg)
    return levels