#! /usr/bin/perl =head1 NAME RbdLib.pm - Perl Module that contains the functions used by CLI script for testing RBD. =cut package RbdLib; use Cwd; use Exporter; @ISA = 'Exporter'; @EXPORT_OK = qw(perform_action create_image resize_image rename_image copy_image list_image info_image export_image import_image remove_image create_snapshots protect_snapshot clone_image unprotect_snapshot rollback_snapshots purge_snapshots list_snapshots remove_snapshot rbd_map rbd_unmap rbd_showmapped display_result _pre_clean_up _post_clean_up _create_rados_pool display_ceph_os_info $RADOS_LS $RADOS_MKPOOL $RADOS_RMPOOL $RBD_CREATE $RBD_RESIZE $RBD_INFO $RBD_REMOVE $RBD_RENAME $RBD_MV $RBD_LS $RBD_LIST $RBD_CLONE $RBD_EXPORT $RBD_IMPORT $RBD_CP $RBD_COPY $SNAP_CREATE $SNAP_LS $SNAP_LIST $SNAP_ROLLBACK $SNAP_PURGE $SNAP_REMOVE $RBD_CHILDREN $RBD_FLATTEN $POOL_RM_SUCCESS $POOL_MK_SUCCESS $RBD_EXISTS_ERR $RBD_WATCH $RBD_MAP $RBD_UNMAP $RBD_SHOWMAPPED $RBD_FLATTEN $SNAP_PROTECT $SNAP_UNPROTECT get_command_output verify_action debug_msg tpass tfail log_results display_func_result $CLI_FLAG ); use Pod::Usage(); use Getopt::Long(); use strict; use warnings; $|=1; # variables our $TC_CNT = " "; our $PASS_CNT = 0; our $TPASS_CNT = 0; our $FAIL_CNT = 0; our $TFAIL_CNT = 0; our $RADOS_MKPOOL = "rados mkpool"; our $RADOS_RMPOOL = "rados rmpool"; our $RBD_CREATE = "rbd create"; our $RBD_RESIZE = "rbd resize"; our $RBD_INFO = "rbd info"; our $RBD_REMOVE = "rbd rm"; our $RBD_RENAME = "rbd rename"; our $RBD_MV = "rbd mv"; our $RBD_LS = "rbd ls"; our $RBD_LIST = "rbd list"; our $RBD_CLONE = "rbd clone"; our $RBD_EXPORT = "rbd export"; our $RBD_IMPORT = "rbd import"; our $RBD_COPY = "rbd copy"; our $RBD_CP = "rbd cp"; our $SNAP_CREATE = "rbd snap create"; our $SNAP_LIST = "rbd snap list"; our $SNAP_LS = "rbd snap ls"; our $SNAP_ROLLBACK = "rbd snap rollback"; our $SNAP_REMOVE = "rbd snap rm"; our $SNAP_PURGE = "rbd snap purge"; our $RBD_WATCH = "rbd watch"; our $RBD_MAP = "sudo rbd map"; our $RBD_UNMAP = "sudo rbd unmap"; our $RBD_SHOWMAPPED = "rbd showmapped"; our $RADOS_LS = "rados ls"; our $SNAP_PROTECT = "rbd snap protect"; our $SNAP_UNPROTECT = "rbd snap unprotect"; our $RBD_CHILDREN = "rbd children"; our $RBD_FLATTEN = "rbd flatten"; #====Error messages======================== our $RBD_CREATE_ERR = "size must be >= 0"; our $RBD_EXTRA_ERR = "extraneous parameter"; our $RBD_REQ_ERR = "expected integer"; our $RBD_RM_ERROR = "image name was not specified"; our $SNAP_LS_ERROR = "snap name was not specified"; our $SNAP_RM_ERROR = "remove failed"; our $SNAP_ROLLBACK_ERR = "rollback failed"; our $RBD_CP_ERROR = "error: destination image name"; our $RBD_EXISTS_ERR = "exists"; our $RBD_RENAME_ERROR = "rename error"; our $RBD_DELETE_ERROR = "delete error"; our $RBD_NO_IMAGE = "error opening image"; our $RBD_POOL_ERROR = "error opening pool"; our $RBD_INT_ERR = "expected integer"; our $RBD_ARG_ERR = "requires an argument"; our $RBD_EXP_ERR = "export error"; our $RBD_IMP_ERR = "import failed"; our $RBD_MAP_ERR = "add failed"; our $RBD_UNMAP_ERR = "remove failed"; our $RBD_INFO_SNAP_ERR = "error setting snapshot context"; our $SNAP_PROTECT_ERR = "Device or resource busy"; our $SNAP_PROTECT_RM_ERR = "protected from removal"; our $SNAP_PROTECT_ERR1 = "No such file or directory"; our $SNAP_UNPROT_ERR = "snap_unprotect: image must support layering"; our $SNAP_UNPROT_ERR1 = "snap_unprotect: can't unprotect"; #our $SNAP_UNPROTECT_ERR - bug # 4045 our $SNAP_PROT_ERR = "snap_protect: image must support layering"; our $CLONE_UNPROTECT_ERR = "parent snapshot must be protected"; our $CLONE_ARG_ERR = "destination image name was not specified"; our $CLONE_PARENT_ERR = "error opening parent image"; our $CLONE_PF_ERR = "parent image must be in new format"; our $FLATTEN_ERR = "librbd: parent snapshot must be protected"; our $FLATTEN_IMG_ERR = "librbd: image has no parent"; #=======Success messages======================= our $POOL_MK_SUCCESS = "successfully created pool"; our $POOL_RM_SUCCESS = "successfully deleted pool"; our $RBD_RM_SUCCESS = "Removing image: 100%"; our $RBD_CP_SUCCESS = "Image copy: 100%"; our $RBD_RESIZE_SUCCESS = "Resizing image: 100%"; our $RBD_EXP_SUCCESS = "Exporting image: 100%"; our $RBD_IMP_SUCCESS = "Importing image: 100%"; our $SNAP_ROLLBACK_SUCCESS = "Rolling back to snapshot: 100%"; our $SNAP_PURGE_SUCCESS = "Removing all snapshots: 100%"; our $RBD_FLATTEN_SUCCESS = "Image flatten: 100% complete"; #===========Variables used in the script======== our $test_log = "logfile.txt"; our $success_file = "test_completed.txt"; our $log_file = "log.txt"; our $exec_cmd; our $PASS_FLAG = "FALSE"; our $TPASS_FLAG = "FALSE"; our $MSG; our $rbd_imp_file = "test_file"; our $exp_file = "rbd_test_file1"; our $exp_file1 = "rbd_test_file2"; our $rbd_imp_test = "new_test_file"; our $img_name = "test_img"; our $pool_name; our $rc = " "; our $CLI_FLAG; sub _post_clean_up { my $exec_cmd = get_command_output( "rm -rf $img_name $rbd_imp_file $rbd_imp_test $exp_file $exp_file1" ); } sub _pre_clean_up { my $exec_cmd = get_command_output( "rm -rf logfile.txt log.txt test_completed.txt" ); } sub perform_action { my ( $action, $cmd_args, $option ) = @_; my $command = frame_command( $action, $cmd_args, $option ); my $cmd_op = get_command_output($command); my $rc = validate_cmd_output( $cmd_op, $action, $cmd_args, $option ); return $rc; } sub verify_action { my ( $action, $cmd_args, $option ) = @_; my $command = frame_command( $action, $cmd_args, $option ); my $cmd_op = get_command_output($command); return $cmd_op; } sub pass { my ($comment) = @_; print "Comment required." unless length $comment; chomp $comment; print_border2(); print "Test case: $TC_CNT PASSED - $comment \n"; print_border2(); $PASS_CNT++; $PASS_FLAG = "TRUE"; $MSG = "$comment"; log_cli_results(); } sub tpass { my ($comment) = @_; print "Comment required." unless length $comment; chomp $comment; print_border4(); print "PASS: $comment \n"; print_border4(); $TPASS_CNT++; $TPASS_FLAG = "TRUE"; $MSG = "$comment"; log_results(); } sub fail { my ($comment) = @_; print "Comment required." unless length $comment; chomp $comment; print_border2(); print "Test case: $TC_CNT FAILED - $comment \n"; print_border2(); $FAIL_CNT++; $PASS_FLAG = "FALSE"; $MSG = "$comment"; log_cli_results(); } sub tfail { my ($comment) = @_; print "Comment required." unless length $comment; chomp $comment; print_border4(); print "FAIL: $comment \n"; print_border4(); $TFAIL_CNT++; $TPASS_FLAG = "FALSE"; $MSG = "$comment"; log_results(); } sub debug_msg { my ($comment,$is_debug) = @_; print "Comment required." unless length $comment; chomp $comment; print_border3(); if (!$is_debug){ print "DEBUG: $comment \n"; } else { print "$comment \n"; } print_border3(); } sub print_border { print "=" x 90 . "\n"; } sub print_border2 { print "~" x 90 . "\n"; } sub print_border3 { print "+" x 90 . "\n"; } sub print_border4 { print "*" x 90 . "\n"; } sub banner { my ($string) = @_; chomp $string; print_border(); print $string, "\n"; print_border(); } sub display_result { banner("TEST RESULTS"); banner( "No. of test cases passed:$PASS_CNT\nNo. of test cases failed:$FAIL_CNT\n" ); } sub display_func_result { banner("TEST RESULTS"); banner( "No. of test cases passed:$TPASS_CNT\nNo. of test cases failed:$TFAIL_CNT\n" ); } sub get_command_output { my $cmd_output = shift; open( FH, ">>$test_log" ); print FH "*" x 90 . "\n"; print FH "\"$cmd_output\"\n"; my $exec_cmd = `$cmd_output 2>&1`; print FH "$exec_cmd\n"; print FH "*" x 90 . "\n"; close(FH); return $exec_cmd; } sub frame_command { my ( $action, $cmd_args, $option ) = @_; my @command_set = split( /,/, $cmd_args ); my $command = join( ' --', @command_set ); $command = "$action $command"; return $command; } sub check_if_listed { my ( $chk_cmd, $check_arg, $cmd, $args ) = @_; my $check_op = get_command_output($chk_cmd); if ( $check_op =~ /$check_arg/ ) { pass("$cmd $args passed"); return 0; } else { fail("$cmd $args failed"); return 1; } } sub check_if_not_listed { my ( $chk_cmd, $check_arg, $cmd, $args ) = @_; my $check_op = get_command_output($chk_cmd); if ( $check_op =~ /$check_arg/ ) { fail("$cmd $args failed"); return 1; } else { pass("$cmd $args passed"); return 0; } } sub validate_cmd_output { $TC_CNT++ if ( $CLI_FLAG eq "TRUE" ) ; $PASS_FLAG = "FALSE"; $MSG = " "; my ( $arg, $snap, $arg1, $parg ); my $snaps; my ( $cmd_op, $act, $args, $test_flag ) = @_; if ( !$test_flag ) { if ( ( $act =~ /$RBD_CREATE/ ) && ( !$cmd_op ) ) { $arg = ( split /,/, $args )[0]; $parg = ( split /,/, $args )[1]; $pool_name = ( split / /, $parg )[1]; $rc = check_if_listed( "$RBD_LS $pool_name", $arg, $act , $args); return $rc; } elsif (( ( $act =~ /$RBD_RENAME/ ) || ( $act =~ /$RBD_MV/ ) ) && ( !$cmd_op ) ) { $arg = ( split /\//, $args )[-1]; $pool_name = ( split /\//, $args )[0]; $rc = check_if_listed( "$RBD_LS $pool_name", $arg, $act, $args ); return $rc; } elsif ( ( $act =~ /$SNAP_CREATE/ ) && ( !$cmd_op ) ) { $snaps = ( split / /, $args )[1]; $arg = ( split / /, $args )[2]; $rc = check_if_listed( "$SNAP_LS $arg", $snaps, $act, $args ); return $rc; } elsif ( ( $act =~ /$SNAP_REMOVE/ ) && ( !$cmd_op ) ) { $snaps = ( split /\@/, $args )[-1]; $arg1 = ( split /\@/, $args )[-2]; $arg = ( split /\//, $arg1 )[-1]; $pool_name = ( split /\@/,$args )[0]; $rc = check_if_not_listed( "$SNAP_LS $pool_name", $snaps , $act, $args); return $rc; } elsif (( $act =~ /$SNAP_PURGE/ ) && ( $cmd_op =~ /$SNAP_PURGE_SUCCESS/ ) ) { pass("$act $args passed"); } elsif ( $act =~ /$RBD_INFO/ ) { $arg = ( split /\//, $args )[-1]; my $rbd_img_quoted = "\'$arg\'"; pass("$act $args passed") if ( $cmd_op =~ /rbd image $rbd_img_quoted/ ); } elsif ( ( $act =~ /$RBD_REMOVE/ ) && ( $cmd_op =~ /$RBD_RM_SUCCESS/ ) ) { $pool_name = ( split /\//, $args )[0]; my $img_name = ( split /\//, $args )[1]; $rc = check_if_not_listed( "$RBD_LS $pool_name",$img_name , $act, $args ); return $rc; } elsif (( $act =~ /$RBD_RESIZE/ ) && ( $cmd_op =~ /$RBD_RESIZE_SUCCESS/ ) ) { pass("$act $args passed"); } elsif (( ( $act =~ /$RBD_COPY/ ) || ( $act =~ /$RBD_CP/ ) ) && ( $cmd_op =~ /$RBD_CP_SUCCESS/ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$RBD_EXPORT/ ) && ( ( $cmd_op =~ /$RBD_EXP_SUCCESS/ ) || ( $cmd_op =~ /$RBD_EXISTS_ERR/ ) ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$RBD_IMPORT/ ) && ( ( $cmd_op =~ /$RBD_IMP_SUCCESS/ ) || ( $cmd_op =~ /$RBD_EXISTS_ERR/ ) ) ) { pass("$act $args passed"); } elsif (( $act =~ /$SNAP_ROLLBACK/ ) && ( $cmd_op =~ /$SNAP_ROLLBACK_SUCCESS/ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$RBD_SHOWMAPPED/ ) && ( $cmd_op =~ /$img_name/ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$RBD_MAP/ ) && ( $cmd_op !~ /./ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$SNAP_PROTECT/ ) && ( $cmd_op !~ /./ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$SNAP_UNPROTECT/ ) && ( $cmd_op !~ /./ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$RBD_CLONE/ ) && ( $cmd_op !~ /./ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$RBD_FLATTEN/ ) && ( $cmd_op =~ /$RBD_FLATTEN_SUCCESS/ ) ) { pass("$act $args passed"); } elsif ( ( $act =~ /$RBD_UNMAP/ ) && ( $cmd_op !~ /$RBD_UNMAP_ERR/ ) ) { pass("$act $args passed"); } else { if ( $cmd_op =~ /$RBD_EXISTS_ERR/ ) { pass("$act $args $RBD_EXISTS_ERR"); } else { fail("$act $args failed"); return 1; } } return 0; } elsif ( ( $test_flag == 1 ) && ( $cmd_op =~ /$RBD_EXISTS_ERR/ ) ) { pass("Already exists: $act $args passed"); return 0; } elsif ( ( $test_flag == 2 ) && ( ( $cmd_op =~ /$RBD_RENAME_ERROR/ ) || ( $cmd_op =~ /$RBD_DELETE_ERROR/ ) || ( $cmd_op =~ /$RBD_NO_IMAGE/ ) || ( $cmd_op =~ /$RBD_POOL_ERROR/ ) || ( $cmd_op =~ /$RBD_INT_ERR/ ) || ( $cmd_op =~ /$RBD_ARG_ERR/ ) || ( $cmd_op =~ /$RBD_RM_ERROR/ ) || ( $cmd_op =~ /$SNAP_LS_ERROR/ ) || ( $cmd_op =~ /$SNAP_RM_ERROR/ ) || ( $cmd_op =~ /$RBD_CP_ERROR/ ) || ( $cmd_op =~ /$RBD_EXP_ERR/ ) || ( $cmd_op =~ /$RBD_IMP_ERR/ ) || ( $cmd_op =~ /$SNAP_ROLLBACK_ERR/ ) || ( $cmd_op =~ /$RBD_MAP_ERR/ ) || ( $cmd_op =~ /$RBD_UNMAP_ERR/ ) || ( $cmd_op =~ /$RBD_CREATE_ERR/ ) || ( $cmd_op =~ /$RBD_EXTRA_ERR/ ) || ( $cmd_op =~ /$RBD_REQ_ERR/ ) || ( $cmd_op =~ /$SNAP_PROTECT_ERR/ ) || ( $cmd_op =~ /$SNAP_PROTECT_ERR1/ ) || ( $cmd_op =~ /$SNAP_PROTECT_RM_ERR/ ) || ( $cmd_op =~ /$SNAP_PROT_ERR/ ) || ( $cmd_op =~ /$SNAP_UNPROT_ERR/ ) || ( $cmd_op =~ /$SNAP_UNPROT_ERR1/ ) || ( $cmd_op =~ /$CLONE_UNPROTECT_ERR/ ) || ( $cmd_op =~ /$CLONE_ARG_ERR/ ) || ( $cmd_op =~ /$CLONE_PARENT_ERR/ ) || ( $cmd_op =~ /$CLONE_PF_ERR/ ) || ( $cmd_op =~ /$FLATTEN_ERR/ ) || ( $cmd_op =~ /$FLATTEN_IMG_ERR/ ) || ( $cmd_op =~ /$RBD_INFO_SNAP_ERR/ ) ) ) { pass("negative case: $act $args passed"); return 0; } elsif ( ( $test_flag == 3 ) && ( $cmd_op =~ /usage/ ) ) { pass("negative case: $act $args passed"); return 0; } else { fail("negative case:$act $args failed"); return 1; } } # Test Script execution results for Functional tests sub log_results { if ( $TPASS_FLAG eq "TRUE" ) { open( TC, '>>test_completed.txt' ); close(TC); open( TC, '>>log.txt' ); print TC "[Success] $MSG\n"; close(TC); } else { open( TC, '>>test_completed.txt' ); close(TC); open( TC, '>>log.txt' ); print TC "[Failure] $MSG\n"; close(TC); } } # Test Script execution results for CLI tests sub log_cli_results { if ($CLI_FLAG eq "TRUE") { if ( $PASS_FLAG eq "TRUE" ) { open( TC, '>>test_completed.txt' ); close(TC); open( TC, '>>log.txt' ); print TC "[Success] TestCase $TC_CNT $MSG\n"; close(TC); } else { open( TC, '>>test_completed.txt' ); close(TC); open( TC, '>>log.txt' ); print TC "[Failure] TestCase $TC_CNT $MSG\n"; close(TC); } } } sub ceph_os_info { my $ceph_v = get_command_output ( "ceph -v" ); my @ceph_arr = split(" ",$ceph_v); $ceph_v = "Ceph Version: $ceph_arr[2]"; my $os_distro = get_command_output ( "lsb_release -d" ); my @os_arr = split(":",$os_distro); $os_distro = "Linux Flavor:$os_arr[1]"; return ($ceph_v, $os_distro); } sub display_ceph_os_info { my ($vceph, $vos) = ceph_os_info(); my $dat = get_command_output ( "date" ); my $msg = "The Tests were executed on $dat"; debug_msg ( "$msg\n$vos$vceph\n",1 ); open( TC, '>>log.txt' ); print TC "[Log] $vceph\n"; close (TC); } 1;