-
garciadeblas authored
Change-Id: I6827fc17f79a99668205d74ae297fcfb41c1bb00 Signed-off-by:
garciadeblas <gerardo.garciadeblas@telefonica.com>
c5a51c40
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
generate_descriptor_pkg.sh 23.29 KiB
#!/bin/bash
############################################################################
# Copyright 2016 RIFT.io Inc #
# #
# 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. #
############################################################################
#
# This shell script is used to create a descriptor package
# The main functions of this script include:
# - Generate checksums.txt file
# - Generate a tar.gz file
# This script can be used to create the required folders for
# a descriptor package and a template descriptor
# Usage: generate_descriptor_pkg.sh <base-directory> <package-directory>
# Descriptor names should be
# - (nsd|vnfd).(yaml|yml|json|xml)
# - *_(nsd|vnfd).(yaml|yml|json|xml)
# - *_(nsd|vnfd)_*.(yaml|yml|json|xml)
# - (nsd|vnfd)/*.(yaml|yml|json|xml)
#
SCRIPTNAME=`basename $0`
# From https://osm.etsi.org/wikipub/index.php/Release_0_Data_Model_Details
# Supported folders for VNFD
# cloud_init - Rel 4.3, not yet part of OSM
VNFD_FOLDERS=(images scripts icons charms cloud_init)
# Supported folders for NSD
# OSM document specifies (ns|vnf)-config folder, while Rel 4.3
# is using (ns|vnf)_config.
NSD_FOLDERS=(scripts charms icons ns_config vnf_config)
# Other files allowed in the descriptor base directory
ALLOWED_FILES=(README)
ALLOWED_FILES_WILDCARDS=(README)
DESC_TYPES=(vnfd nsd)
DESC_EXTN=(yml yaml json xml)
CHKSUM='checksums.txt'
VERBOSE=false
DRY_RUN=false
CREATE=false
RM="--remove-files"
DEBUG=false
ARCHIVE=false
CREATE_NSD=false
VENDOR='OSM'
INTF_TYPE='PARAVIRT'
VCPU=2
MEMORY=4096
STORAGE=10
INTERFACES=1
function usage() {
cat <<EOF
Usage:
$SCRIPTNAME [-t <type>] [-N] [-c] [base-directory] <package-name>
-h|--help : show this message
-t|--package-type <nsd|vnfd> : Descriptor package type
is NSD or VNFD. Script will try to
determine the type if not provided.
Default is vnfd for create-folders.
-d|--destination-dir <destination directory>: Directory to create the
archived file.
Default is base-directory
-N|--no-remove-files : Do not remove the package files after creating
archive
Options specifc for create descriptor:
-c|--create-folder : Create folder with the structure for the
package type using the base-dir and package-dir
and a descriptor template
-a|--archive: Create package for the descriptor
--nsd : Generate NSD descriptor package also.
--vendor : Vendor name for descriptor. Default OSM
--interface-type : Interface type [PARAVIRT|SR-IOV|PCI-PASSTHROUGH|E1000]
Default PARAVIRT
VM Flavour options:
--vcpu : Virtual CPU count. Default 2
--memory : Memory for VM in MB. Default 4096MB
--storage : Storage size for VM in GB. Default 10GB
VDU Parameters:
--image : Location URI of the image
--cloud-init-file : Cloud init file
--cloud-init : Cloud init script. Will be ignored if
cloud-init-file is specified
--interfaces : Number of external interfaces in additon to OM-MGMT. Default 1.
End of create descriptor specific options
-v| --verbose : Generate progress details
-n| --dry-run : Validate the package dir
base-dir : Directory where the archive file or folders are created,
if destination directory is not specified.
Default is current directory
package-name : The descriptor name (full path if base-dir not specified)
EOF
}
CP_TYPE='VPORT'
function get_cp_type() {
case ${INTF_TYPE} in
PARAVIRT ) CP_TYPE='VPORT';;
SR-IOV ) CP_TYPE='VPORT';;
PCI-PASSTHROUGH ) CP_TYPE='VPORT';;
OM-MGMT ) CP_TYPE='VPORT';;
E1000 ) CP_TYPE='VPORT';;
* ) echo "ERROR: Unknown interface type ${INTF_TYPE}"; exit 1;;
esac
}
# Get pci number starting from 0x0a
get_pci() {
printf '%02x' $((10 + $1)) | tr '[:upper:]' '[:lower:]'
}
function write_readme() {
dir=$1
file=${dir}/README
date=$(date)
cat >$file <<EOF
Descriptor created by OSM descriptor package generated
Created on $date
EOF
}
function write_vnfd_tmpl() {
name=$(basename $1)
desc_file="${name}.yaml"
cat >$desc_file <<EOF
vnfd:vnfd-catalog:
vnfd:
- id: ${name}
name: ${name}
short-name: ${name}
description: Generated by OSM package generator
vendor: ${VENDOR}
version: '1.0'
# Place the logo as png in icons directory and provide the name here
# logo: <update, optional>
# Management interface
mgmt-interface:
cp: vnf-cp0
# Atleast one VDU need to be specified
vdu:
# Additional VDUs can be created by copying the
# VDU descriptor below
- id: ${name}-VM
name: ${name}-VM
description: ${name}-VM
count: 1
# Flavour of the VM to be instantiated for the VDU
vm-flavor:
vcpu-count: ${VCPU}
memory-mb: ${MEMORY}
storage-gb: ${STORAGE}
# Image including the full path
image: '${IMAGE}'
EOF
# Add the cloud init file or script
if [[ -n ${CLOUD_INIT_FILE} ]]; then
cif=$(basename ${CLOUD_INIT_FILE})
cat >>$desc_file <<EOF
# Cloud init file
cloud-init-file: '${cif}'
EOF
elif [[ -n ${CLOUD_INIT} ]]; then
cat >>$desc_file <<EOF
# Cloud init to use
cloud-init: '${CLOUD_INIT}'
EOF
fi
# Add external interfaces
cat >>$desc_file <<EOF
interface:
# Specify the external interfaces
# There can be multiple interfaces defined
EOF
# Add mgmt interface
cat >>$desc_file <<EOF
- name: eth0
type: EXTERNAL
virtual-interface:
type: PARAVIRT
external-connection-point-ref: vnf-cp0
EOF
# Add external interfaces
for i in `seq 1 ${INTERFACES}`; do
eth=$(($i))
cat >>$desc_file <<EOF
- name: eth${eth}
type: EXTERNAL
virtual-interface:
type: ${INTF_TYPE}
external-connection-point-ref: vnf-cp${eth}
EOF
done
# Add connection points
cat >>$desc_file <<EOF
connection-point:
EOF
for i in `seq 0 ${INTERFACES}`; do
eth=$(($i))
cat >>$desc_file <<EOF
- name: vnf-cp${eth}
EOF
done
cat >>$desc_file <<EOF
# Uncomment and update below to enable juju
# charm configuration for the VNF
# vnf-configuration:
# juju:
# charm: <charm name>
# service-primitive:
# - name: config
# parameter:
# - name: <config parameter>
# data-type: [STRING|INTEGER]
# mandatory: [true|false]
# default-value: <value>
# - name: <action name>
# parameter:
# - name: <action parameter>
# data-type: [STRING|INTEGER]
# mandatory: [true|false]
# default-value: <value>
# initial-config-primitive:
# - name: config
# parameter:
# - name: <config name>
# value: <value>
# - name: <action name>
# parameter:
# - name: <action parameter>
# value: <value>
EOF
if [ $VERBOSE == true ]; then
echo "INFO: Created $desc_file"
fi
}
function write_nsd_tmpl() {
name=$(basename $1)
vnfd=$2
desc_file="${name}.yaml"
cat >$desc_file <<EOF
nsd:nsd-catalog:
nsd:
- id: ${name}
name: ${name}
short-name: ${name}
description: Generated by OSM package generator
vendor: ${VENDOR}
version: '1.0'
# Place the logo as png in icons directory and provide the name here
# logo: <update, optional>
# Specify the VNFDs that are part of this NSD
constituent-vnfd:
# The member-vnf-index needs to be unique, starting from 1
# vnfd-id-ref is the id of the VNFD
# Multiple constituent VNFDs can be specified
- member-vnf-index: 1
vnfd-id-ref: ${vnfd}
EOF
cat >>$desc_file <<EOF
vld:
# Networks for the VNFs
EOF
# Add management VLD
cat >>$desc_file <<EOF
- id: ${name}_vld0
name: management
short-name: management
type: ELAN
mgmt-network: 'true'
# vim-network-name: <update>
# provider-network:
# overlay-type: VLAN
# segmentation_id: <update>
vnfd-connection-point-ref:
# Specify the constituent VNFs
# member-vnf-index-ref - entry from constituent vnf
# vnfd-id-ref - VNFD id
# vnfd-connection-point-ref - connection point name in the VNFD
- member-vnf-index-ref: 1
vnfd-id-ref: ${vnfd}
# NOTE: Validate the entry below
vnfd-connection-point-ref: vnf-cp0
EOF
# Add rest of VLDs
for i in `seq 1 ${INTERFACES}`; do
eth=$(($i))
cat >>$desc_file <<EOF
- id: ${name}_vld${i}
name: ${name}_vld${i}
short-name: ${name}_vld${i}
type: ELAN
# vim-network-name: <update>
# provider-network:
# overlay-type: VLAN
# segmentation_id: <update>
vnfd-connection-point-ref:
# Specify the constituent VNFs
# member-vnf-index-ref - entry from constituent vnf
# vnfd-id-ref - VNFD id
# vnfd-connection-point-ref - connection point name in the VNFD
- member-vnf-index-ref: 1
vnfd-id-ref: ${vnfd}
# NOTE: Validate the entry below
vnfd-connection-point-ref: vnf-cp${eth}
EOF
done
if [ $VERBOSE == true ]; then
echo "INFO: Created $desc_file"
fi
}
function write_nsd_config_tmpl() {
name=$(basename $1)
cfg_file="ns_config/$name.yaml"
cat >$cfg_file <<EOF
EOF
if [ $VERBOSE == true ]; then
echo "INFO: Created $cfg_file"
fi
}
cur_dir=`pwd`
# Check if the array contains a specific value
# Taken from
# http://stackoverflow.com/questions/3685970/check-if-an-array-contains-a-value
function contains() {
local n=$#
local value=${!n}
for ((i=1;i < $#;i++)); do
if [ "${!i}" == "${value}" ]; then
echo "y"
return 0
fi
done
echo "n"
return 1
}
function check_type() {
type=$1
if [ $(contains "${DESC_TYPES[@]}" $type) == "y" ]; then
TYPE=$type
else
echo "ERROR: Unknown descriptor type $type!" >&2
exit 1
fi
}
function get_expr(){
# First argument is to specify if this is a negative match or not
# Rest are filename expressions without extension
local regex=" "
local n=$#
local neg="${1}"
local first="true"
for ((i=2;i <= $#;i++)); do
for extn in "${DESC_EXTN[@]}"; do
if [ $first == true ]; then
if [ $neg == true ]; then
subexpr='! -name'
else
subexpr='-name'
fi
first=false
else
if [ $neg == true ]; then
subexpr=' -a ! -name'
else
subexpr=' -o -name'
fi
fi
regex="$regex $subexpr ${!i}.$extn"
done
done
echo "$regex"
}
function generate_package(){
type=$1
name="${2}_${type}"
vnfd="${2}_vnfd" # Required for NSD
dest_dir=$3
dir="${dest_dir}/${name}"
# Create the folders for the descriptor
if [ $VERBOSE == true ]; then
echo "INFO: Creating folders for $PKG in $dest_dir"
fi
# Remove any existing directory
if [ -d $dir ]; then
rm -rf $dir >/dev/null 2>&1
fi
mkdir -p $dir && cd $dir
if [ $? -ne 0 ]; then
rc=$?
echo "ERROR: creating directory $dir ($rc)" >&2
exit $rc
fi
if [ $type == 'nsd' ]; then
folders=("${NSD_FOLDERS[@]}")
else
folders=("${VNFD_FOLDERS[@]}")
fi
for d in ${folders[@]}; do
mkdir -p $dir/$d
if [ $? -ne 0 ]; then
rc=$?
echo "ERROR: creating directory $dir/$d ($rc)" >&2
exit $rc
fi
if [ $VERBOSE == true ]; then
echo "Created folder $d in $dir"
fi
done
if [ $VERBOSE == true ]; then
echo "INFO: Created folders for in $dir"
fi
# Write a descriptor template file
if [ $type == 'vnfd' ]; then
# Copy cloud init file to correct folder
if [[ -n ${CLOUD_INIT_FILE} ]]; then
if [[ -e ${CLOUD_INIT_FILE} ]]; then
cp ${CLOUD_INIT_FILE} $dir/cloud_init
else
echo "ERROR: Unable to find cloud-init-file ${CLOUD_INIT_FILE}"
exit 1
fi
fi
write_vnfd_tmpl $dir
else
write_nsd_tmpl $dir $vnfd
fi
write_readme $dir
if [ $ARCHIVE == true ]; then
# Create archive of the package
cd $dest_dir
if [ $VERBOSE == true ]; then
tar zcvf ${name}.tar.gz ${name}
echo "Created package ${name}.tar.gz in $dest_dir"
else
tar zcvf ${name}.tar.gz ${name} >/dev/null 2>&1
fi
if [ $? -ne 0 ]; then
echo "ERROR: Creating archive for ${name} in $dest_dir" >&2
exit 1
fi
echo "$dest_dir/${name}.tar.gz" >&2
if [ $RM == true ]; then
rm -rf ${name}
fi
fi
}
OPTS=`getopt -o vhnt:d:caN --long verbose,dry-run,help,package-type:,destination-dir,create-folder,no-remove-files,archive,nsd,vendor:,interface-type:,vcpu:,memory:,storage:,image:,cloud-init-file:,cloud-init:,interfaces:,debug -n $SCRIPTNAME -- "$@"`
if [ $? != 0 ] ; then
echo "ERROR: Failed parsing options ($?)." >&2
usage
exit 1
fi
#echo "$OPTS"
eval set -- "$OPTS >/dev/null 2>&1"
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-h | --help ) usage; exit 0; shift ;;
-n | --dry-run ) DRY_RUN=true; shift ;;
-t | --package-type ) check_type "$2"; shift; shift ;;
-d | --destination-dir ) DEST_DIR=$2; shift; shift;;
-c | --create-folder ) CREATE=true; shift;;
-N | --no-remove-files ) RM=''; shift;;
-a | --archive ) ARCHIVE=true; shift;;
--nsd ) CREATE_NSD=true; shift;;
--vendor ) VENDOR=$2; shift; shift;;
--interface-type ) INTF_TYPE=$2; shift; shift;;
--vcpu ) VCPU=$2; shift; shift;;
--memory ) MEMORY=$2; shift; shift;;
--storage ) STORAGE=$2; shift; shift;;
--image ) IMAGE=$2; shift; shift;;
--cloud-init ) CLOUD_INIT=$2; shift; shift;;
--cloud-init-file ) CLOUD_INIT_FILE=$2; shift; shift;;
--interfaces ) INTERFACES=$2; shift; shift;;
--debug ) DEBUG=true; shift;;
-- ) shift; break ;;
* ) break ;;
esac
done
if [ $DEBUG == true ]; then
echo "INFO: Debugging ON"
set -x
fi
if [ $VERBOSE == true ]; then
echo "INFO: Descriptor type: $TYPE"
fi
# Dry run is to validate existing descriptor folders
if [ $DRY_RUN == true ] && [ $CREATE == true ]; then
echo "ERROR: Option dry-run with create-folders not supported!" >&2
exit 1
fi
if [ $# -gt 1 ]; then
BASE_DIR=$1
PKG=$(basename $2)
else
BASE_DIR=$(dirname $1)
PKG=$(basename $1)
fi
if [ $VERBOSE == true ]; then
echo "INFO: Using base dir: $BASE_DIR"
fi
if [ $VERBOSE == true ]; then
echo "INFO: Using package: $PKG"
fi
if [[ -z "$PKG" ]]; then
echo "ERROR: Need to specify the package name" >&2
usage >&2
exit 1
fi
if [[ ! -d $BASE_DIR ]]; then
if [ $CREATE == true ]; then
mkdir -p $BASE_DIR
if [ $? -ne 0 ]; then
echo "ERROR: Unable to create base directory $BASE_DIR" >&2
exit 1
fi
fi
fi
cd $BASE_DIR
if [ $? -ne 0 ]; then
echo "ERROR: Unable to change to base directory $BASE_DIR!" >&2
exit 1
fi
# Get full base dir path
BASE_DIR=`pwd`
cd $cur_dir
if [[ -z $DEST_DIR ]]; then
DEST_DIR=$BASE_DIR # Default to base directory
fi
mkdir -p $DEST_DIR
cd $DEST_DIR
if [ $? -ne 0 ]; then
echo "ERROR: Not able to access destination directory $DEST_DIR!" >&2
exit 1
fi
# Get the full destination dir path
DEST_DIR=`pwd`
cd $cur_dir
dir=${BASE_DIR}/${PKG}
function add_chksum() {
if [ $VERBOSE == true ]; then
echo "INFO: Add file $1 to $CHKSUM"
fi
md5sum $1 >> $CHKSUM
}
if [ $CREATE == false ]; then
if [ ! -d $dir ]; then
echo "INFO: Package folder $dir not found!" >&2
exit 1
fi
cd $dir
if [ $? -ne 0 ]; then
rc=$?
echo "ERROR: changing directory to $dir ($rc)" >&2
exit $rc
fi
# Remove checksum file, if present
rm -f $CHKSUM
# Check if the descriptor file is present
if [[ -z $TYPE ]]; then
# Desc type not specified, look for the desc file and guess the type
# Required for backward compatibility
for ty in ${DESC_TYPES[@]}; do
re=$(get_expr false "$ty" "*_$ty" "*_${ty}_*")
desc=$(find * -maxdepth 0 -type f $re 2>/dev/null)
if [[ -z $desc ]] || [ ${#desc[@]} -eq 0 ]; then
# Check the vnfd|nsd folder
if [ ! -d $ty ]; then
continue
fi
re=$(get_expr false "*")
desc=$(find $ty/* -maxdepth 0 -type f $re 2>/dev/null)
if [[ -z $desc ]] || [ ${#desc[@]} -eq 0 ]; then
continue
elif [ ${#desc[@]} -gt 1 ]; then
echo "ERROR: Found multiple descriptor files: ${desc[@]}" >&2
exit 1
fi
# Descriptor sub directory
desc_sub_dir=$ty
fi
TYPE=$ty
if [ $TYPE == 'nsd' ]; then
folders=("${NSD_FOLDERS[@]}")
else
folders=("${VNFD_FOLDERS[@]}")
fi
if [ $VERBOSE == true ]; then
echo "INFO: Determined descriptor is of type $TYPE"
fi
break
done
if [[ -z $TYPE ]]; then
echo "ERROR: Unable to determine the descriptor type!" >&2
exit 1
fi
else
if [ $TYPE == 'nsd' ]; then
folders=("${NSD_FOLDERS[@]}")
else
folders=("${VNFD_FOLDERS[@]}")
fi
# Check for descriptor of type provided on command line
re=$(get_expr false "$TYPE" "*_${TYPE}" "*_${TYPE}_*")
desc=$(find * -maxdepth 0 -type f $re 2>/dev/null)
if [[ -z $desc ]] || [ ${#desc[@]} -eq 0 ]; then
# Check if it is under vnfd/nsd subdirectory
# Backward compatibility support
re=$(get_expr false "*")
desc=$(find $TYPE/* -maxdepth 0 -type f $re 2>/dev/null)
if [[ -z $desc ]] || [ ${#desc[@]} -eq 0 ]; then
echo "ERROR: Did not find descriptor file of type $TYPE" \
" in $dir" >&2
exit 1
fi
desc_sub_dir=$ty
fi
fi
if [ ${#desc[@]} -gt 1 ]; then
echo "ERROR: Found multiple files of type $TYPE in $dir: $desc" >&2
exit 1
fi
descriptor=${desc[0]}
# Check if there are files not supported
files=$(find * -maxdepth 0 -type f ! -name $descriptor 2>/dev/null)
for f in ${files[@]}; do
if [ $(contains "${ALLOWED_FILES[@]}" $f) == "n" ]; then
for j in ${ALLOWED_FILES_WILDCARDS[@]}; do
if [[ $f != *"$j"* ]]; then
echo "WARN: Unsupported file $f found"
fi
done
fi
done
if [ $VERBOSE == true ]; then
echo "INFO: Found descriptor package: ${desc_sub_dir} ${descriptor}"
fi
if [ $DRY_RUN == false ]; then
add_chksum ${descriptor}
fi
# Check the folders are supported ones
dirs=$( find * -maxdepth 0 -type d )
for d in ${dirs[@]}; do
if [ $(contains "${folders[@]}" $d) == "y" ]; then
if [ $DRY_RUN == false ]; then
find $d/* -type f 2>/dev/null|
while read file; do
add_chksum $file
done
fi
elif [[ -z $desc_sub_dir ]] || [ $d != $desc_sub_dir ]; then
echo "WARN: $d is not part of standard folders " \
"for descriptor type $TYPE in $PKG"
fi
done
if [ $VERBOSE == true ]; then
echo "INFO: Creating archive for $PKG"
fi
cd $BASE_DIR
# Mrityunjay Yadav: Validate descriptor
GEN_BASEDIR=$(dirname "$0")
python3 $GEN_BASEDIR/validate_descriptor.py $BASE_DIR/$PKG/$descriptor
if [ $? -ne 0 ]; then
rc=$?
echo "ERROR: validating descriptor for $PKG ($rc)" >&2
exit $rc
fi
if [ $DRY_RUN == false ]; then
if [ $VERBOSE == true ]; then
tar zcvf "$DEST_DIR/$PKG.tar.gz" "${PKG}" ${RM}
else
#tar zcvf ${name}.tar.gz ${name} >/dev/null 2>&1
tar zcvf "$DEST_DIR/$PKG.tar.gz" "${PKG}" ${RM} > /dev/null 2>&1
fi
if [ $? -ne 0 ]; then
rc=$?
echo "ERROR: creating archive for $PKG ($rc)" >&2
exit $rc
fi
fi
else
# Create, default to VNFD if no type is defined
if [[ -z $TYPE ]]; then
TYPE=vnfd
if [ $VERBOSE == true ]; then
echo "WARNING: Defaulting to descriptor type $TYPE"
fi
fi
if [ $TYPE == 'vnfd' ]; then
if [[ -z $IMAGE ]]; then
echo "ERROR: Image file need to be specified for VNF"
exit 1
fi
generate_package vnfd $PKG $DEST_DIR
fi
if [ $TYPE == 'nsd' -o $CREATE_NSD == true ]; then
generate_package nsd $PKG $DEST_DIR
fi
fi
cd $cur_dir