651216e
#!/usr/bin/python
651216e
651216e
# Copyright (c) 2017 Red Hat, Inc. All rights reserved. This copyrighted material
651216e
# is made available to anyone wishing to use, modify, copy, or
651216e
# redistribute it subject to the terms and conditions of the GNU General
651216e
# Public License v.2.
651216e
#
651216e
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
651216e
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
651216e
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
651216e
#
651216e
# You should have received a copy of the GNU General Public License
651216e
# along with this program; If not, see http://www.gnu.org/licenses/.
651216e
#
651216e
# Author: Jakub Krysl <jkrysl@redhat.com>
651216e
651216e
import sys, os
651216e
sys.path.append(os.path.abspath("dmpd_library.py"))
651216e
651216e
from dmpd_library import *
651216e
651216e
def thin_init(args):
651216e
    # Create thin pool with LVs
651216e
    print("INFO: Initializing test case")
651216e
    errors = []
651216e
651216e
    atomic_run("Creating loopdev",
651216e
               name=args["loop1"],
651216e
               size=args["loop1_size"],
651216e
               command=loopdev.create_loopdev,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating VG",
651216e
               vg_name=args["group"],
651216e
               pv_name="/dev/" + args["loop1"],
651216e
               command=lvm.vg_create,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating thin pool",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["pool"],
651216e
               options=["-T", "-L 500"],
651216e
               command=lvm.lv_create,
651216e
               errors=errors)
651216e
651216e
    # create few LVs to increase transaction ID and be able to do thin_delta
651216e
    for i in range(args["number of vols"]):
651216e
        atomic_run("Creating thin LV No. %s" % i,
651216e
                   vg_name=args["group"] + "/" + args["pool"],
651216e
                   lv_name=args["vol"] + str(i),
651216e
                   options=["-T", "-V 100"],
651216e
                   command=lvm.lv_create,
651216e
                   errors=errors)
651216e
651216e
        atomic_run("Creating filesystem on LV No. %s" % i,
651216e
                   vg_name=args["group"],
651216e
                   lv_name=args["vol"] + str(i),
651216e
                   command=create_filesystem,
651216e
                   errors=errors)
651216e
651216e
        atomic_run("Deactivating thin LV No. %s" % i,
651216e
                   lv_name=args["vol"] + str(i),
651216e
                   vg_name=args["group"],
651216e
                   command=lvm.lv_deactivate,
651216e
                   errors=errors)
651216e
651216e
    atomic_run("Creating metadata snapshot",
651216e
               lv_name=args["pool"],
651216e
               vg_name=args["group"],
651216e
               command=metadata_snapshot,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deactivating pool",
651216e
               lv_name=args["pool"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_deactivate,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating swap LV",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["swap"],
651216e
               options=["-L 100"],
651216e
               command=lvm.lv_create,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deactivating swap",
651216e
               lv_name=args["swap"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_deactivate,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Swapping metadata",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["swap"],
651216e
               options=["-y", "--thinpool " + args["group"] + "/" + args["pool"],
651216e
                        "--poolmetadata "],
651216e
               command=lvm.lv_convert,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Activating swap",
651216e
               lv_name=args["swap"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_activate,
651216e
               errors=errors)
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Initialization passed")
651216e
    else:
651216e
        TC.tfail("Initialization failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        return 1
651216e
    return 0
651216e
651216e
651216e
def thin_clean(args):
651216e
    print("INFO: Cleaning up")
651216e
    errors = []
651216e
651216e
    # restoring metadata device in case it is corrupted
651216e
    atomic_run("Repairing metadata device",
651216e
               source_file="/tmp/metadata",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               quiet=True,
651216e
               command=dmpd.thin_restore,
651216e
               errors=errors)
651216e
651216e
    # thinpool got activated after checking its metadata to get bad checksum
651216e
    atomic_run("Deactivating pool",
651216e
               lv_name=args["pool"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_deactivate,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deactivating swap",
651216e
               lv_name=args["swap"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_deactivate,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Swapping back metadata",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["swap"],
651216e
               options=["-y", "--thinpool " + args["group"] + "/" + args["pool"],
651216e
                        "--poolmetadata "],
651216e
               command=lvm.lv_convert,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Removing swap",
651216e
               lv_name=args["swap"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_remove,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Removing thinpool",
651216e
               lv_name=args["pool"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_remove,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Removing VG",
651216e
               vg_name=args["group"],
651216e
               force=True,
651216e
               command=lvm.vg_remove,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting loopdev",
651216e
               name=args["loop1"],
651216e
               command=loopdev.delete_loopdev,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting metadata file",
651216e
               cmd="rm -f /tmp/metadata",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting repair metadata file",
651216e
               cmd="rm -f /tmp/metadata_repair",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting snapshot metadata file",
651216e
               cmd="rm -f /tmp/metadata_snap",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Cleanup passed")
651216e
    else:
651216e
        TC.tfail("Cleanup failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        print(errors)
651216e
        return 1
651216e
    return 0
651216e
651216e
def thin_test(args):
651216e
    print("\n#######################################\n")
651216e
    print (
651216e
        "INFO: Testing thin tools runtime provided by device_mapper_persistent_data")
651216e
651216e
    errors = []
651216e
651216e
    atomic_run("Checking metadata",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.thin_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata with few paramethers",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               super_block_only=True,
651216e
               skip_mappings=True,
651216e
               ignore_non_fatal_errors=True,
651216e
               command=dmpd.thin_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Listing information about thin LVs",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.thin_ls,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Listing information about thin LVs without headers",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               no_headers=True,
651216e
               command=dmpd.thin_ls,
651216e
               errors=errors)
651216e
651216e
    # Not yet in Fedora 26, shoud be in F27
651216e
    #atomic_run("Dumping metadata to standard output without mappings",
651216e
    #           formatting="human_readable",
651216e
    #           source_vg=args["group"],
651216e
    #           source_lv=args["swap"],
651216e
    #           skip_mappings=True,
651216e
    #           command=dmpd.thin_dump,
651216e
    #           errors=errors)
651216e
651216e
    atomic_run("Dumping metadata to standard output",
651216e
               formatting="human_readable",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.thin_dump,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Dumping metadata to standard output from snapshot",
651216e
               formatting="human_readable",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               snapshot=True,
651216e
               command=dmpd.thin_dump,
651216e
               errors=errors)
651216e
651216e
    # Not yet in Fedora 26, shoud be in F27
651216e
    #atomic_run("Dumping metadata with dev-id",
651216e
    #           formatting="human_readable",
651216e
    #           source_vg=args["group"],
651216e
    #           source_lv=args["swap"],
651216e
    #           dev_id=args["number of vols"] - 1,
651216e
    #           command=dmpd.thin_dump,
651216e
    #           errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for pool of 64k blocks and 100M size",
651216e
               cmd="thin_metadata_size -b64k -s100m -m1 -um",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for pool of 64k blocks and 100M size",
651216e
               cmd="thin_metadata_size -b64k -s100m -m1 -um -n",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for pool of 64k blocks and 100M size",
651216e
               cmd="thin_metadata_size -b64k -s100m -m1 -um -nlong",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for pool of 64k blocks and 100M size",
651216e
               cmd="thin_metadata_size -b64k -s100m -m1 -um -nshort",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Outputting reverse map of metadata device",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               region="0..-1",
651216e
               command=dmpd.thin_rmap,
651216e
               errors=errors)
651216e
651216e
    # this fails now and it should not
651216e
    # atomic_run("Discarding free space of pool",
651216e
    #           target_vg=args["group"],
651216e
    #           target_lv=args["swap"],
651216e
    #           command=dmpd.thin_trim,
651216e
    #           errors=errors)
651216e
651216e
    atomic_run("Dumping metadata to file",
651216e
               formatting="xml",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               repair=True,
651216e
               output="/tmp/metadata",
651216e
               command=dmpd.thin_dump,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Dumping metadata to file from snapshot",
651216e
               formatting="xml",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               snapshot=True,
651216e
               output="/tmp/metadata_snap",
651216e
               command=dmpd.thin_dump,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Getting differences between thin LVs",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               thin1=1,
651216e
               thin2=args["number of vols"] - 1,
651216e
               snapshot=True,
651216e
               command=dmpd.thin_delta,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Getting differences between thin LVs with --verbose",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               thin1=1,
651216e
               thin2=args["number of vols"] - 1,
651216e
               verbosity=True,
651216e
               snapshot=True,
651216e
               command=dmpd.thin_delta,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Getting differences between the same LV",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               thin1=1,
651216e
               thin2=1,
651216e
               snapshot=True,
651216e
               command=dmpd.thin_delta,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Getting differences between the same LV with --verbose",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               thin1=1,
651216e
               thin2=1,
651216e
               verbosity=True,
651216e
               snapshot=True,
651216e
               command=dmpd.thin_delta,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Listing metadata output from snapshot",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               snapshot=True,
651216e
               command=dmpd.thin_ls,
651216e
               errors=errors)
651216e
651216e
    # Need to run everything on snapshot before this as thin_restore removes the metadata snapshot
651216e
    # This should work but is not working due to a bug
651216e
    #atomic_run("Restoring metadata",
651216e
    #           source_file="/tmp/metadata_snap",
651216e
    #           target_vg=args["group"],
651216e
    #           target_lv=args["swap"],
651216e
    #           command=dmpd.thin_restore,
651216e
    #           errors=errors)
651216e
651216e
    atomic_run("Restoring metadata",
651216e
               source_file="/tmp/metadata",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               command=dmpd.thin_restore,
651216e
               errors=errors)
651216e
651216e
    #   Repairing from non-binary file leads to segmentation fault
651216e
    #atomic_run("Repairing metadata from file",
651216e
    #            source_file="/tmp/metadata",
651216e
    #            target_vg=args["group"],
651216e
    #            target_lv=args["swap"],
651216e
    #            command=dmpd.thin_repair,
651216e
    #            errors=errors)
651216e
651216e
    atomic_run("Repairing metadata to file",
651216e
               target_file="/tmp/metadata_repair",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.thin_repair,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata from file",
651216e
               source_file="/tmp/metadata_repair",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               command=dmpd.thin_repair,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.thin_check,
651216e
               errors=errors)
651216e
651216e
    print("\n#######################################\n")
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Testing thin tools of device_mapper_persistent_data passed")
651216e
    else:
651216e
        TC.tfail("Testing thin tools of device_mapper_persistent_data failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        return 1
651216e
    return 0
651216e
651216e
651216e
def thin_errors_test(args):
651216e
    print("\n#######################################\n")
651216e
    print (
651216e
        "INFO: Testing thin tools errors provided by device_mapper_persistent_data")
651216e
651216e
    errors = []
651216e
651216e
    # "thin_show_duplicates" does not work yet
651216e
    functions = ["thin_check", "thin_delta", "thin_dump", "thin_ls", "thin_metadata_size", "thin_repair",
651216e
                 "thin_restore", "thin_rmap", "thin_trim"]
651216e
651216e
    # Sanity to check for missing input
651216e
    for func in functions:
651216e
        atomic_run("Validating missing input",
651216e
                   False,
651216e
                   cmd=func,
651216e
                   command=run,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check with wrong input
651216e
    for func in functions:
651216e
        atomic_run("Validating wrong input",
651216e
                   False,
651216e
                   cmd=func + " wrong",
651216e
                   command=run,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check with wrong option
651216e
    for func in functions:
651216e
        atomic_run("Validating wrong option",
651216e
                   False,
651216e
                   cmd=func + " -wrong",
651216e
                   command=run,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check present functions with -h
651216e
    for func in functions:
651216e
        atomic_run("Checking help of command",
651216e
                   cmd=func,
651216e
                   command=dmpd.get_help,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check present functions with -V
651216e
    for func in functions:
651216e
        # thin_metadata_size has wrong return value
651216e
        if func == "thin_metadata_size":
651216e
            continue
651216e
        atomic_run("Checking version of command",
651216e
                   cmd=func,
651216e
                   command=dmpd.get_version,
651216e
                   errors=errors)
651216e
651216e
    atomic_run("Checking original pool metadata, should fail",
651216e
               False,
651216e
               source_vg=args["group"],
651216e
               source_lv=args["pool"],
651216e
               command=dmpd.thin_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Listing information about thin LVs",
651216e
               False,
651216e
               cmd="thin_ls /dev/mapper/%s-%s --format \"WRONG\"" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -b 64",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -b 64 -s 128",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -b 25 -s 128 -m 10",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -b 128 -s 64 -m 10",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -u h",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -n -n",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -nlongshort",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking thin_metadata_size inputs",
651216e
               False,
651216e
               cmd="thin_metadata_size -b 128 -b 64",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata without output",
651216e
               False,
651216e
               cmd="thin_repair -i /tmp/metadata_repair",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Dumping metadata with wrong custom format",
651216e
               False,
651216e
               cmd="thin_dump /dev/mapper/%s-%s --format custom=wrong" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Dumping metadata with unknown format",
651216e
               False,
651216e
               cmd="thin_dump /dev/mapper/%s-%s --format wrong" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Dumping metadata with wrong dev-id",
651216e
               False,
651216e
               cmd="thin_dump /dev/mapper/%s-%s --dev-id wrong" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata to produce 'output file does not exist' error",
651216e
               False,
651216e
               cmd="thin_repair -i /dev/mapper/%s-%s -o /tmp/wrong.wrong" %
651216e
                   (args['group'], args['swap']),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata to produce 'output file too small' error",
651216e
               False,
651216e
               cmd="thin_repair -i /tmp/metadata -o /tmp/metadata",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    # This does not fail now due to a bug
651216e
    #atomic_run("Outputting reverse map of metadata device, should fail without region",
651216e
    #           cmd="thin_rmap /dev/mapper/%s-%s" % (args["group"], args["swap"]),
651216e
    #           command=run,
651216e
    #           errors=errors)
651216e
651216e
    atomic_run("Outputting reverse map of metadata device with wrong region",
651216e
               False,
651216e
               cmd="thin_rmap /dev/mapper/%s-%s --region 0..0" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Outputting reverse map of metadata device with wrong region",
651216e
               False,
651216e
               cmd="thin_rmap /dev/mapper/%s-%s --region 0...1" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Outputting reverse map of metadata device with wrong region",
651216e
               False,
651216e
               cmd="thin_rmap /dev/mapper/%s-%s --region 00" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Outputting reverse map of metadata device with wrong device",
651216e
               False,
651216e
               cmd="thin_rmap --region 0..-1 /tmp/wrong.wrong",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    #   Reverse mapping from bad file leads to segmentation fault
651216e
    #atomic_run("Outputting reverse map of metadata device with wrong device",
651216e
    #            False,
651216e
    #            cmd="thin_rmap --region 0..-1 /tmp/metadata",
651216e
    #            command=run,
651216e
    #            errors=errors)
651216e
651216e
    atomic_run("Getting differences with thin1 ID out of range",
651216e
               False,
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               thin1=-1,
651216e
               thin2=args["number of vols"] - 1,
651216e
               command=dmpd.thin_delta,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Getting differences with thin2 ID out of range",
651216e
               False,
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               thin1=1,
651216e
               thin2=args["number of vols"] + 1,
651216e
               command=dmpd.thin_delta,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata without output",
651216e
               False,
651216e
               cmd="thin_restore -i /tmp/metadata",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata with wrong options",
651216e
               False,
651216e
               cmd="thin_restore -i /tmp/metadata -o /dev/mapper/%s-%s --wrong test" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata with wrong source",
651216e
               False,
651216e
               cmd="thin_restore -i /tmp/wrong.wrong -o /dev/mapper/%s-%s" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Getting differences without thin2",
651216e
               False,
651216e
               cmd="thin_delta --thin1 1 /dev/mapper/%s-%s" %
651216e
                   (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Corrupting metadata on device",
651216e
               cmd="echo 'nothing' >> /dev/mapper/%s-%s" %
651216e
                   (args['group'], args['swap']),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Trying to fail while repairing metadata",
651216e
               False,
651216e
               source_vg=args['group'],
651216e
               source_lv=args['swap'],
651216e
               target_file="/tmp/metadata_repair",
651216e
               command=dmpd.thin_repair,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Trying to fail listing volumes",
651216e
               False,
651216e
               source_vg=args['group'],
651216e
               source_lv=args['swap'],
651216e
               command=dmpd.thin_ls,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Trying to fail while checking metadata",
651216e
               False,
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.thin_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Trying to fail while dumping metadata from snapshot",
651216e
               False,
651216e
               formatting="human_readable",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               snapshot=True,
651216e
               command=dmpd.thin_dump,
651216e
               errors=errors)
651216e
651216e
    # restoring metadata device after corrupting it
651216e
    atomic_run("Repairing metadata device",
651216e
               source_file="/tmp/metadata",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               quiet=True,
651216e
               command=dmpd.thin_restore,
651216e
               errors=errors)
651216e
651216e
    print("\n#######################################\n")
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Testing thin tools errors of device_mapper_persistent_data passed")
651216e
    else:
651216e
        TC.tfail("Testing thin tools errors of device_mapper_persistent_data failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        return 1
651216e
    return 0
651216e
651216e
651216e
def cache_init(args):
651216e
    print("INFO: Initializing test case")
651216e
    errors = []
651216e
651216e
    atomic_run("Creating loopdev 1 - 'fast' device",
651216e
               name=args["loop1"],
651216e
               size=args["loop1_size"],
651216e
               command=loopdev.create_loopdev,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating loopdev 2 - 'slow' device",
651216e
               name=args["loop2"],
651216e
               size=args["loop2_size"],
651216e
               command=loopdev.create_loopdev,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating VG",
651216e
               vg_name=args["group"],
651216e
               pv_name="/dev/" + args["loop1"] +
651216e
                       " /dev/" + args["loop2"],
651216e
               command=lvm.vg_create,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating cache metadata volume",
651216e
               vg_name=args["group"] + " /dev/" + args["loop1"],
651216e
               lv_name=args["meta"],
651216e
               options=["-L 12"],
651216e
               command=lvm.lv_create,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating origin volume",
651216e
               vg_name=args["group"] + " /dev/" + args["loop2"],
651216e
               lv_name=args["origin"],
651216e
               options=["-L 2G"],
651216e
               command=lvm.lv_create,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating cache data volume",
651216e
               vg_name=args["group"] + " /dev/" + args["loop1"],
651216e
               lv_name=args["data"],
651216e
               options=["-L 1G"],
651216e
               command=lvm.lv_create,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating cache pool",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["data"],
651216e
               options=["-y --type cache-pool", "--cachemode writeback", "--poolmetadata %s/%s" %
651216e
                       (args["group"], args["meta"])],
651216e
               command=lvm.lv_convert,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating cache logical volume",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["origin"],
651216e
               options=["-y", "--type cache", "--cachepool %s/%s" %
651216e
                       (args["group"], args["data"])],
651216e
               command=lvm.lv_convert,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating filesystem on cache logical volume",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["origin"],
651216e
               command=create_filesystem,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Splitting cache logical volume",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["origin"],
651216e
               options=["-y", "--splitcache"],
651216e
               command=lvm.lv_convert,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Creating swap LV",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["swap"],
651216e
               options=["-L 100"],
651216e
               command=lvm.lv_create,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Swapping metadata",
651216e
               vg_name=args["group"],
651216e
               lv_name=args["swap"],
651216e
               options=["-y", "--cachepool " + args["group"] + "/" + args["data"],
651216e
                        "--poolmetadata "],
651216e
               command=lvm.lv_convert,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Activating swap",
651216e
               lv_name=args["swap"],
651216e
               vg_name=args["group"],
651216e
               command=lvm.lv_activate,
651216e
               errors=errors)
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Initialization passed")
651216e
    else:
651216e
        TC.tfail("Initialization failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        return 1
651216e
    return 0
651216e
651216e
651216e
def cache_clean(args):
651216e
    print("INFO: Cleaning up")
651216e
    errors = []
651216e
651216e
    atomic_run("Removing VG",
651216e
               vg_name=args["group"],
651216e
               force=True,
651216e
               command=lvm.vg_remove,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting loopdev loop1",
651216e
               name=args["loop1"],
651216e
               command=loopdev.delete_loopdev,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting loopdev loop2",
651216e
               name=args["loop2"],
651216e
               command=loopdev.delete_loopdev,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting metadata file",
651216e
               cmd="rm -f /tmp/metadata",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Deleting repair metadata file",
651216e
               cmd="rm -f /tmp/metadata_repair",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Cleanup passed")
651216e
    else:
651216e
        TC.tfail("Cleanup failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        print(errors)
651216e
        return 1
651216e
    return 0
651216e
651216e
651216e
def cache_test(args):
651216e
    print("\n#######################################\n")
651216e
    print ("INFO: Testing cache tools runtime provided by device_mapper_persistent_data")
651216e
651216e
    errors = []
651216e
651216e
    atomic_run("Checking metadata",
651216e
               source_lv=args["swap"],
651216e
               source_vg=args["group"],
651216e
               command=dmpd.cache_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata with clear-need-check-flag",
651216e
               source_lv=args["swap"],
651216e
               source_vg=args["group"],
651216e
               clear_needs_check_flag=True,
651216e
               command=dmpd.cache_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata with super-block-only",
651216e
               source_lv=args["swap"],
651216e
               source_vg=args["group"],
651216e
               super_block_only=True,
651216e
               command=dmpd.cache_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata with few paramethers",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               skip_discards=True,
651216e
               skip_mappings=True,
651216e
               skip_hints=True,
651216e
               command=dmpd.cache_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Dumping metadata to standard output",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.cache_dump,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for cache of 64 blocks and 128 size",
651216e
               cmd="cache_metadata_size --block-size 64 --device-size 128",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for cache of 128 nr blocks",
651216e
               cmd="cache_metadata_size --nr-blocks 128 --max-hint-width 4",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Dumping metadata to file",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               repair=True,
651216e
               output="/tmp/metadata",
651216e
               command=dmpd.cache_dump,
651216e
               errors=errors)
651216e
651216e
    # Not yet in Fedora 26, shoud be in F27
651216e
    #atomic_run("Checking metadata file",
651216e
    #           source_file="/tmp/metadata",
651216e
    #           command=dmpd.cache_check,
651216e
    #           errors=errors)
651216e
    #
651216e
    #atomic_run("Restoring metadata with options",
651216e
    #           source_file="/tmp/metadata",
651216e
    #           target_vg=args["group"],
651216e
    #           target_lv=args["swap"],
651216e
    #           quiet=True,
651216e
    #           override_metadata_version=1,
651216e
    #           metadata_version=1,
651216e
    #           command=dmpd.cache_restore,
651216e
    #           errors=errors)
651216e
651216e
    atomic_run("Restoring metadata from file",
651216e
               source_file="/tmp/metadata",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               command=dmpd.cache_restore,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata to file",
651216e
               target_file="/tmp/metadata_repair",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.cache_repair,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata from file",
651216e
               source_file="/tmp/metadata_repair",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               command=dmpd.cache_repair,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Simulating TTY for cache_restore",
651216e
               cmd="script --return -c 'cache_restore -i /tmp/metadata -o /dev/mapper/%s-%s' /dev/null" %
651216e
                   (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata",
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               quiet=True,
651216e
               command=dmpd.cache_check,
651216e
               errors=errors)
651216e
651216e
    print("\n#######################################\n")
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Testing cache tools of device_mapper_persistent_data passed")
651216e
    else:
651216e
        TC.tfail("Testing cache tools of device_mapper_persistent_data failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        return 1
651216e
    return 0
651216e
651216e
651216e
def cache_errors_test(args):
651216e
    print("\n#######################################\n")
651216e
    print ("INFO: Testing cache tools errors provided by device_mapper_persistent_data")
651216e
651216e
    errors = []
651216e
651216e
    functions = ["cache_check", "cache_dump", "cache_metadata_size", "cache_repair", "cache_restore"]
651216e
651216e
    # Sanity to check for missing input
651216e
    for func in functions:
651216e
        atomic_run("Validating missing input",
651216e
                   False,
651216e
                   cmd=func,
651216e
                   command=run,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check with wrong input
651216e
    for func in functions:
651216e
        atomic_run("Validating wrong input",
651216e
                   False,
651216e
                   cmd=func + " wrong",
651216e
                   command=run,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check with wrong option
651216e
    for func in functions:
651216e
        atomic_run("Validating wrong option",
651216e
                   False,
651216e
                   cmd=func + " -wrong",
651216e
                   command=run,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check with wrong -- option
651216e
    for func in functions:
651216e
        atomic_run("Validating wrong -- option",
651216e
                   False,
651216e
                   cmd=func + " --wrong",
651216e
                   command=run,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check present functions with -h
651216e
    for func in functions:
651216e
        atomic_run("Checking help of command",
651216e
                   cmd="%s" % func,
651216e
                   command=dmpd.get_help,
651216e
                   errors=errors)
651216e
651216e
    # Sanity to check present functions with -V
651216e
    for func in functions:
651216e
        atomic_run("Checking version of command",
651216e
                   cmd="%s" % func,
651216e
                   command=dmpd.get_version,
651216e
                   errors=errors)
651216e
651216e
    atomic_run("Checking metadata of non-metadata file",
651216e
               False,
651216e
               cmd="cache_check README",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata of non-existent file",
651216e
               False,
651216e
               cmd="cache_check WRONG",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking metadata of non-regular file",
651216e
               False,
651216e
               cmd="cache_check /dev/mapper/control",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for cache of 64 blocks",
651216e
               False,
651216e
               cmd="cache_metadata_size --block-size 64",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for cache of 128 size",
651216e
               False,
651216e
               cmd="cache_metadata_size --device-size 128",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Calculating metadata size for cache of 64 blocks and 128 size and 128 nr blocks",
651216e
               False,
651216e
               cmd="cache_metadata_size --block-size 64 --device-size 128 --nr-blocks 128",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata without output",
651216e
               False,
651216e
               cmd="cache_repair -i /tmp/metadata_repair",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata with wrong options",
651216e
               False,
651216e
               cmd="cache_restore -i /tmp/metadata -o /dev/mapper/%s-%s --wrong test" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata with wrong metadata version",
651216e
               False,
651216e
               source_file="/tmp/metadata",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               metadata_version=12445,
651216e
               command=dmpd.cache_restore,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata with wrong source",
651216e
               False,
651216e
               cmd="cache_restore -i /tmp/wrong.wrong -o /dev/mapper/%s-%s" % (args["group"], args["swap"]),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata with bit source",
651216e
               False,
651216e
               source_file="/tmp/metadata_repair",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               command=dmpd.cache_restore,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Restoring metadata without output",
651216e
               False,
651216e
               cmd="cache_restore -i /tmp/metadata",
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    # I am not able to run cache_restore with --omit-clean-shutdown successfully
651216e
    #atomic_run("Restoring metadata with options",
651216e
    #           source_file="/tmp/metadata",
651216e
    #           target_vg=args["group"],
651216e
    #           target_lv=args["swap"],
651216e
    #           omit_clean_shutdown=True,
651216e
    #           command=dmpd.cache_restore,
651216e
    #           errors=errors)
651216e
651216e
    # This fails in Fedora 26, should work in F27
651216e
    #atomic_run("Checking metadata",
651216e
    #           source_vg=args["group"],
651216e
    #           source_lv=args["swap"],
651216e
    #           command=dmpd.cache_check,
651216e
    #           errors=errors)
651216e
651216e
    #FIXME: Find other way to corrupt metadata, this exploits a bug
651216e
    atomic_run("Corrupting mappings on metadata device",
651216e
               False,
651216e
               source_file="Makefile",
651216e
               target_vg=args["group"],
651216e
               target_lv=args["swap"],
651216e
               command=dmpd.cache_restore,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking corrupted mappings",
651216e
               False,
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.cache_check,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Trying to fail while dumping metadata",
651216e
               False,
651216e
               source_vg=args['group'],
651216e
               source_lv=args['swap'],
651216e
               output="/tmp/metadata",
651216e
               command=dmpd.cache_dump,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Repairing metadata",
651216e
               source_vg=args['group'],
651216e
               source_lv=args['swap'],
651216e
               target_file="/tmp/metadata_repair",
651216e
               command=dmpd.cache_repair,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Corrupting metadata on device",
651216e
               cmd="echo 'nothing' >> /dev/mapper/%s-%s" % (args['group'], args['swap']),
651216e
               command=run,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Trying to fail while repairing metadata",
651216e
               False,
651216e
               source_vg=args['group'],
651216e
               source_lv=args['swap'],
651216e
               target_file="/tmp/metadata_repair",
651216e
               command=dmpd.cache_repair,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Trying to fail while dumping metadata",
651216e
               False,
651216e
               source_vg=args['group'],
651216e
               source_lv=args['swap'],
651216e
               output="/tmp/metadata",
651216e
               command=dmpd.cache_dump,
651216e
               errors=errors)
651216e
651216e
    atomic_run("Checking corrupted metadata",
651216e
               False,
651216e
               source_vg=args["group"],
651216e
               source_lv=args["swap"],
651216e
               command=dmpd.cache_check,
651216e
               errors=errors)
651216e
651216e
651216e
    print("\n#######################################\n")
651216e
651216e
    if len(errors) == 0:
651216e
        TC.tpass("Testing cache tools errors of device_mapper_persistent_data passed")
651216e
    else:
651216e
        TC.tfail("Testing cache tools errors of device_mapper_persistent_data failed with following errors: \n\t'" +
651216e
                 "\n\t ".join([str(i) for i in errors]))
651216e
        return 1
651216e
    return 0
651216e
651216e
651216e
def main():
651216e
    # Initialize Test Case
651216e
    global TC
651216e
    TC = TestClass()
651216e
651216e
    # Initialize library classes
651216e
    global loopdev
651216e
    global lvm
651216e
    global dmpd
651216e
    loopdev = LoopDev()
651216e
    lvm = LVM()
651216e
    dmpd = DMPD()
651216e
651216e
    args = {"loop1": "loop1",
651216e
            "loop1_size": 2048,
651216e
            "loop2": "loop2",
651216e
            "loop2_size": 4128,
651216e
            "group": "vgtest",
651216e
            "origin": "origin",
651216e
            "data": "cache_data",
651216e
            "meta": "cache_meta",
651216e
            "pool": "pool",
651216e
            "vol": "thinvol",
651216e
            "number of vols": 10,
651216e
            "swap": "swapvol"}
651216e
651216e
    # Initialization
651216e
    install_package("device-mapper-persistent-data")
651216e
651216e
    # Tests for thin tools provided by device-mapper-persistent-data
651216e
    thin_init(args)
651216e
    thin_test(args)
651216e
    thin_errors_test(args)
651216e
    thin_clean(args)
651216e
651216e
    # Tests for cache tools provided by device-mapper-persistent-data
651216e
    cache_init(args)
651216e
    cache_test(args)
651216e
    cache_errors_test(args)
651216e
    cache_clean(args)
651216e
651216e
    if not TC.tend():
651216e
        print "FAIL: test failed"
651216e
        sys.exit(1)
651216e
651216e
    print "PASS: Test pass"
651216e
    sys.exit(0)
651216e
651216e
651216e
if __name__ == "__main__":
651216e
    main()