3 ############################################################################
4 # Copyright 2016 RIFT.io Inc #
6 # Licensed under the Apache License, Version 2.0 (the "License"); #
7 # you may not use this file except in compliance with the License. #
8 # You may obtain a copy of the License at #
10 # http://www.apache.org/licenses/LICENSE-2.0 #
12 # Unless required by applicable law or agreed to in writing, software #
13 # distributed under the License is distributed on an "AS IS" BASIS, #
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15 # See the License for the specific language governing permissions and #
16 # limitations under the License. #
17 ############################################################################
20 # This shell script is used to create a descriptor package
21 # The main functions of this script include:
22 # - Generate checksums.txt file
23 # - Generate a tar.gz file
24 # This script can be used to create the required folders for
25 # a descriptor package and a template descriptor
27 # Usage: generate_descriptor_pkg.sh <base-directory> <package-directory>
29 # Descriptor names should be
30 # - (nsd|vnfd).(yaml|yml|json|xml)
31 # - *_(nsd|vnfd).(yaml|yml|json|xml)
32 # - *_(nsd|vnfd)_*.(yaml|yml|json|xml)
33 # - (nsd|vnfd)/*.(yaml|yml|json|xml)
36 SCRIPTNAME
=`basename $0`
38 # From https://osm.etsi.org/wikipub/index.php/Release_0_Data_Model_Details
39 # Supported folders for VNFD
40 # cloud_init - Rel 4.3, not yet part of OSM
41 VNFD_FOLDERS
=(images scripts icons charms cloud_init
)
43 # Supported folders for NSD
44 # OSM document specifies (ns|vnf)-config folder, while Rel 4.3
45 # is using (ns|vnf)_config.
46 NSD_FOLDERS
=(scripts icons ns_config vnf_config
)
48 # Other files allowed in the descriptor base directory
49 ALLOWED_FILES
=(README
)
52 DESC_EXTN
=(yml yaml json xml
)
53 CHKSUM
='checksums.txt'
73 $SCRIPTNAME [-t <type>] [-N] [-c] [base-directory] <package-name>
75 -h|--help : show this message
77 -t|--package-type <nsd|vnfd> : Descriptor package type
78 is NSD or VNFD. Script will try to
79 determine the type if not provided.
80 Default is vnfd for create-folders.
82 -d|--destination-dir <destination directory>: Directory to create the
84 Default is base-directory
86 -N|--no-remove-files : Do not remove the package files after creating
89 Options specifc for create descriptor:
91 -c|--create-folder : Create folder with the structure for the
92 package type using the base-dir and package-dir
93 and a descriptor template
95 -a|--archive: Create package for the descriptor
97 --nsd : Generate NSD descriptor package also.
99 --vendor : Vendor name for descriptor. Default OSM
101 --interface-type : Interface type [VIRTIO|SR-IOV|PCI-PASSTHROUGH|E1000]
106 --vcpu : Virtual CPU count. Default 2
108 --memory : Memory for VM in MB. Default 4096MB
110 --storage : Storage size for VM in GB. Default 10GB
114 --image : Location URI of the image
116 --cloud-init-file : Cloud init file
118 --cloud-init : Cloud init script. Will be ignored if
119 cloud-init-file is specified
121 --interfaces : Number of external interfaces in additon to OM-MGMT. Default 1.
123 End of create descriptor specific options
125 -v| --verbose : Generate progress details
127 -n| --dry-run : Validate the package dir
129 base-dir : Directory where the archive file or folders are created,
130 if destination directory is not specified.
131 Default is current directory
133 package-name : The descriptor name (full path if base-dir not specified)
138 function get_cp_type
() {
140 VIRTIO
) CP_TYPE
='VPORT';;
141 SR-IOV
) CP_TYPE
='VPORT';;
142 PCI-PASSTHROUGH
) CP_TYPE
='VPORT';;
143 OM-MGMT
) CP_TYPE
='VPORT';;
144 E1000
) CP_TYPE
='VPORT';;
145 * ) echo "ERROR: Unknown interface type ${INTF_TYPE}"; exit 1;;
149 # Get pci number starting from 0x0a
151 printf '%02x' $
((10 + $1)) |
tr '[:upper:]' '[:lower:]'
154 function write_readme
() {
160 Descriptor created by OSM descriptor package generated
166 function write_vnfd_tmpl
() {
168 desc_file
="${name}.yaml"
170 cat >$desc_file <<EOF
176 description: Generated by OSM pacakage generator
180 # Place the logo as png in icons directory and provide the name here
181 # logo: <update, optional>
183 # Management interface
187 # Atleast one VDU need to be specified
189 # Additional VDUs can be created by copying the
190 # VDU descriptor below
193 description: ${name}-VM
196 # Flavour of the VM to be instantiated for the VDU
200 storage-gb: ${STORAGE}
202 # Image including the full path
207 # Add the cloud init file or script
208 if [[ -n ${CLOUD_INIT_FILE} ]]; then
209 cif
=$
(basename ${CLOUD_INIT_FILE})
210 cat >>$desc_file <<EOF
212 cloud-init-file: '${cif}'
214 elif [[ -n ${CLOUD_INIT} ]]; then
215 cat >>$desc_file <<EOF
217 cloud-init: '${CLOUD_INIT}'
221 # Add external interfaces
222 cat >>$desc_file <<EOF
224 # Specify the external interfaces
225 # There can be multiple interfaces defined
229 cat >>$desc_file <<EOF
235 vnfd-connection-point-ref: eth0
238 # Add external interfaces
239 for i
in `seq 1 ${INTERFACES}`; do
242 cat >>$desc_file <<EOF
247 vpci: '0000:00:${pci}.0'
248 vnfd-connection-point-ref: eth${eth}
252 # Add connection points
253 cat >>$desc_file <<EOF
258 for i
in `seq 0 ${INTERFACES}`; do
260 cat >>$desc_file <<EOF
266 cat >>$desc_file <<EOF
268 # Uncomment and update below to enable juju
269 # charm configuration for the VNF
272 # charm: <charm name>
276 # - name: <config parameter>
277 # data-type: [STRING|INTEGER]
278 # mandatory: [true|false]
279 # default-value: <value>
280 # - name: <action name>
282 # - name: <action parameter>
283 # data-type: [STRING|INTEGER]
284 # mandatory: [true|false]
285 # default-value: <value>
286 # initial-config-primitive:
289 # - name: <config name>
291 # - name: <action name>
293 # - name: <action parameter>
297 if [ $VERBOSE == true
]; then
298 echo "INFO: Created $desc_file"
302 function write_nsd_tmpl
() {
305 desc_file
="${name}.yaml"
307 cat >$desc_file <<EOF
313 description: Generated by OSM pacakage generator
317 # Place the logo as png in icons directory and provide the name here
318 # logo: <update, optional>
320 # Specify the VNFDs that are part of this NSD
322 # The member-vnf-index needs to be unique, starting from 1
323 # vnfd-id-ref is the id of the VNFD
324 # Multiple constituent VNFDs can be specified
325 - member-vnf-index: 1
330 cat >>$desc_file <<EOF
332 # Networks for the VNFs
336 cat >>$desc_file <<EOF
339 short-name: management
342 # vim-network-name: <update>
345 # segmentation_id: <update>
346 vnfd-connection-point-ref:
347 # Specify the constituent VNFs
348 # member-vnf-index-ref - entry from constituent vnf
349 # vnfd-id-ref - VNFD id
350 # vnfd-connection-point-ref - connection point name in the VNFD
351 - nsd:member-vnf-index-ref: 1
352 nsd:vnfd-id-ref: ${vnfd}
353 # NOTE: Validate the entry below
354 nsd:vnfd-connection-point-ref: eth0
358 for i
in `seq 1 ${INTERFACES}`; do
360 cat >>$desc_file <<EOF
361 - id: ${name}_vld${i}
362 name: ${name}_vld${i}
363 short-name: ${name}_vld${i}
365 # vim-network-name: <update>
368 # segmentation_id: <update>
369 vnfd-connection-point-ref:
370 # Specify the constituent VNFs
371 # member-vnf-index-ref - entry from constituent vnf
372 # vnfd-id-ref - VNFD id
373 # vnfd-connection-point-ref - connection point name in the VNFD
374 - nsd:member-vnf-index-ref: 1
375 nsd:vnfd-id-ref: ${vnfd}
376 # NOTE: Validate the entry below
377 nsd:vnfd-connection-point-ref: eth${eth}
381 if [ $VERBOSE == true
]; then
382 echo "INFO: Created $desc_file"
386 function write_nsd_config_tmpl
() {
388 cfg_file
="ns_config/$name.yaml"
394 if [ $VERBOSE == true
]; then
395 echo "INFO: Created $cfg_file"
401 # Check if the array contains a specific value
403 # http://stackoverflow.com/questions/3685970/check-if-an-array-contains-a-value
404 function contains
() {
407 for ((i
=1;i
< $#;i
++)); do
408 if [ "${!i}" == "${value}" ]; then
417 function check_type
() {
419 if [ $
(contains
"${DESC_TYPES[@]}" $type) == "y" ]; then
422 echo "ERROR: Unknown descriptor type $type!" >&2
428 # First argument is to specify if this is a negative match or not
429 # Rest are filename expressions without extension
435 for ((i
=2;i
<= $#;i
++)); do
436 for extn
in "${DESC_EXTN[@]}"; do
437 if [ $first == true
]; then
438 if [ $neg == true
]; then
445 if [ $neg == true
]; then
446 subexpr
=' -a ! -name'
452 regex
="$regex $subexpr ${!i}.$extn"
459 function generate_package
(){
462 vnfd
="${2}_vnfd" # Required for NSD
465 dir
="${dest_dir}/${name}"
467 # Create the folders for the descriptor
468 if [ $VERBOSE == true
]; then
469 echo "INFO: Creating folders for $PKG in $dest_dir"
472 # Remove any existing directory
474 rm -rf $dir >/dev
/null
2>&1
477 mkdir
-p $dir && cd $dir
478 if [ $?
-ne 0 ]; then
480 echo "ERROR: creating directory $dir ($rc)" >&2
484 if [ $type == 'nsd' ]; then
485 folders
=("${NSD_FOLDERS[@]}")
487 folders
=("${VNFD_FOLDERS[@]}")
490 for d
in ${folders[@]}; do
492 if [ $?
-ne 0 ]; then
494 echo "ERROR: creating directory $dir/$d ($rc)" >&2
497 if [ $VERBOSE == true
]; then
498 echo "Created folder $d in $dir"
502 if [ $VERBOSE == true
]; then
503 echo "INFO: Created folders for in $dir"
506 # Write a descriptor template file
507 if [ $type == 'vnfd' ]; then
509 # Copy cloud init file to correct folder
510 if [[ -n ${CLOUD_INIT_FILE} ]]; then
511 if [[ -e ${CLOUD_INIT_FILE} ]]; then
512 cp ${CLOUD_INIT_FILE} $dir/cloud_init
514 echo "ERROR: Unable to find cloud-init-file ${CLOUD_INIT_FILE}"
521 write_nsd_tmpl
$dir $vnfd
526 if [ $ARCHIVE == true
]; then
527 # Create archive of the package
529 if [ $VERBOSE == true
]; then
530 tar zcvf
${name}.
tar.gz
${name}
531 echo "Created package ${name}.tar.gz in $dest_dir"
533 tar zcvf
${name}.
tar.gz
${name} >/dev
/null
2>&1
536 if [ $?
-ne 0 ]; then
537 echo "ERROR: Creating archive for ${name} in $dest_dir" >&2
541 echo "$dest_dir/${name}.tar.gz" >&2
543 if [ $RM == true
]; then
549 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 -- "$@"`
551 if [ $?
!= 0 ] ; then
552 echo "ERROR: Failed parsing options ($?)." >&2
558 eval set -- "$OPTS >/dev/null 2>&1"
562 -v |
--verbose ) VERBOSE
=true
; shift ;;
563 -h |
--help ) usage
; exit 0; shift ;;
564 -n |
--dry-run ) DRY_RUN
=true
; shift ;;
565 -t |
--package-type ) check_type
"$2"; shift; shift ;;
566 -d |
--destination-dir ) DEST_DIR
=$2; shift; shift;;
567 -c |
--create-folder ) CREATE
=true
; shift;;
568 -N |
--no-remove-files ) RM
=''; shift;;
569 -a |
--archive ) ARCHIVE
=true
; shift;;
570 --nsd ) CREATE_NSD
=true
; shift;;
571 --vendor ) VENDOR
=$2; shift; shift;;
572 --interface-type ) INTF_TYPE
=$2; shift; shift;;
573 --vcpu ) VCPU
=$2; shift; shift;;
574 --memory ) MEMORY
=$2; shift; shift;;
575 --storage ) STORAGE
=$2; shift; shift;;
576 --image ) IMAGE
=$2; shift; shift;;
577 --cloud-init ) CLOUD_INIT
=$2; shift; shift;;
578 --cloud-init-file ) CLOUD_INIT_FILE
=$2; shift; shift;;
579 --interfaces ) INTERFACES
=$2; shift; shift;;
580 --debug ) DEBUG
=true
; shift;;
586 if [ $DEBUG == true
]; then
587 echo "INFO: Debugging ON"
591 if [ $VERBOSE == true
]; then
592 echo "INFO: Descriptor type: $TYPE"
595 # Dry run is to validate existing descriptor folders
596 if [ $DRY_RUN == true
] && [ $CREATE == true
]; then
597 echo "ERROR: Option dry-run with create-folders not supported!" >&2
601 if [ $# -gt 1 ]; then
605 BASE_DIR
=$
(dirname $1)
609 if [ $VERBOSE == true
]; then
610 echo "INFO: Using base dir: $BASE_DIR"
613 if [ $VERBOSE == true
]; then
614 echo "INFO: Using package: $PKG"
617 if [[ -z "$PKG" ]]; then
618 echo "ERROR: Need to specify the package name" >&2
623 if [[ ! -d $BASE_DIR ]]; then
624 if [ $CREATE == true
]; then
626 if [ $?
-ne 0 ]; then
627 echo "ERROR: Unable to create base directory $BASE_DIR" >&2
633 if [ $?
-ne 0 ]; then
634 echo "ERROR: Unable to change to base directory $BASE_DIR!" >&2
638 # Get full base dir path
642 if [[ -z $DEST_DIR ]]; then
643 DEST_DIR
=$BASE_DIR # Default to base directory
649 if [ $?
-ne 0 ]; then
650 echo "ERROR: Not able to access destination directory $DEST_DIR!" >&2
654 # Get the full destination dir path
658 dir
=${BASE_DIR}/${PKG}
660 function add_chksum
() {
661 if [ $VERBOSE == true
]; then
662 echo "INFO: Add file $1 to $CHKSUM"
668 if [ $CREATE == false
]; then
669 if [ ! -d $dir ]; then
670 echo "INFO: Package folder $dir not found!" >&2
675 if [ $?
-ne 0 ]; then
677 echo "ERROR: changing directory to $dir ($rc)" >&2
681 # Remove checksum file, if present
684 # Check if the descriptor file is present
685 if [[ -z $TYPE ]]; then
686 # Desc type not specified, look for the desc file and guess the type
687 # Required for backward compatibility
688 for ty
in ${DESC_TYPES[@]}; do
689 re
=$
(get_expr false
"$ty" "*_$ty" "*_${ty}_*")
690 desc
=$
(find * -maxdepth 0 -type f
$re 2>/dev
/null
)
692 if [[ -z $desc ]] ||
[ ${#desc[@]} -eq 0 ]; then
693 # Check the vnfd|nsd folder
694 if [ ! -d $ty ]; then
697 re
=$
(get_expr false
"*")
698 desc
=$
(find $ty/* -maxdepth 0 -type f
$re 2>/dev
/null
)
699 if [[ -z $desc ]] ||
[ ${#desc[@]} -eq 0 ]; then
701 elif [ ${#desc[@]} -gt 1 ]; then
702 echo "ERROR: Found multiple descriptor files: ${desc[@]}" >&2
705 # Descriptor sub directory
710 if [ $TYPE == 'nsd' ]; then
711 folders
=("${NSD_FOLDERS[@]}")
713 folders
=("${VNFD_FOLDERS[@]}")
716 if [ $VERBOSE == true
]; then
717 echo "INFO: Determined descriptor is of type $TYPE"
722 if [[ -z $TYPE ]]; then
723 echo "ERROR: Unable to determine the descriptor type!" >&2
727 if [ $TYPE == 'nsd' ]; then
728 folders
=("${NSD_FOLDERS[@]}")
730 folders
=("${VNFD_FOLDERS[@]}")
733 # Check for descriptor of type provided on command line
734 re
=$
(get_expr false
"$TYPE" "*_${TYPE}" "*_${TYPE}_*")
735 desc
=$
(find * -maxdepth 0 -type f
$re 2>/dev
/null
)
737 if [[ -z $desc ]] ||
[ ${#desc[@]} -eq 0 ]; then
738 # Check if it is under vnfd/nsd subdirectory
739 # Backward compatibility support
740 re
=$
(get_expr false
"*")
741 desc
=$
(find $TYPE/* -maxdepth 0 -type f
$re 2>/dev
/null
)
742 if [[ -z $desc ]] ||
[ ${#desc[@]} -eq 0 ]; then
743 echo "ERROR: Did not find descriptor file of type $TYPE" \
751 if [ ${#desc[@]} -gt 1 ]; then
752 echo "ERROR: Found multiple files of type $TYPE in $dir: $desc" >&2
756 descriptor
=${desc[0]}
758 # Check if there are files not supported
759 files
=$
(find * -maxdepth 0 -type f
! -name $descriptor 2>/dev
/null
)
761 for f
in ${files[@]}; do
762 if [ $
(contains
"${ALLOWED_FILES[@]}" $f) == "n" ]; then
763 echo "WARN: Unsupported file $f found"
767 if [ $VERBOSE == true
]; then
768 echo "INFO: Found descriptor package: ${desc_sub_dir} ${descriptor}"
771 if [ $DRY_RUN == false
]; then
772 add_chksum
${descriptor}
775 # Check the folders are supported ones
776 dirs=$
( find * -maxdepth 0 -type d
)
778 for d
in ${dirs[@]}; do
779 if [ $
(contains
"${folders[@]}" $d) == "y" ]; then
780 if [ $DRY_RUN == false
]; then
781 find $d/* -type f
2>/dev
/null|
786 elif [[ -z $desc_sub_dir ]] ||
[ $d != $desc_sub_dir ]; then
787 echo "WARN: $d is not part of standard folders " \
788 "for descriptor type $TYPE in $PKG"
792 if [ $VERBOSE == true
]; then
793 echo "INFO: Creating archive for $PKG"
797 if [ $DRY_RUN == false
]; then
798 tar zcvf
"$DEST_DIR/$PKG.tar.gz" "${PKG}" ${RM}
799 if [ $?
-ne 0 ]; then
801 echo "ERROR: creating archive for $PKG ($rc)" >&2
806 # Create, default to VNFD if no type is defined
807 if [[ -z $TYPE ]]; then
809 if [ $VERBOSE == true
]; then
810 echo "WARNING: Defaulting to descriptor type $TYPE"
814 if [ $TYPE == 'vnfd' ]; then
815 if [[ -z $IMAGE ]]; then
816 echo "ERROR: Image file need to be specified for VNF"
819 generate_package vnfd
$PKG $DEST_DIR
822 if [ $TYPE == 'nsd' -o $CREATE_NSD == true
]; then
823 generate_package nsd
$PKG $DEST_DIR