import os
import json
import subprocess

from config import logging, client, BASE_PATH, WITHOUT_CEPH


# If you are using WITHOUT_CEPH FLAG in .env
# then please make sure that /var/image directory
# exists otherwise this script would fail
if WITHOUT_CEPH and not os.path.isdir("/var/image"):
    exit(1)


# We want to get images entries that requests images to be created
images = client.get_prefix("/v1/image/", value_in_json=True)
images_to_be_created = filter(lambda im: im.value["status"] == "TO_BE_CREATED", images)

for image in images_to_be_created:
    try:
        image_uuid = image.key.split('/')[-1]
        image_owner = image.value['owner']
        image_filename = image.value['filename']
        image_store_name = image.value['store_name']
        image_full_path = os.path.join(BASE_PATH, image_owner, image_filename)

        image_stores = client.get_prefix("/v1/image_store/", value_in_json=True)
        user_image_store = next(filter(lambda s: s.value["name"] == image_store_name, image_stores))

        image_store_pool = user_image_store.value['attributes']['pool']

    except Exception as e:
        logging.exception(e)
    else:
        # At least our basic data is available

        qemu_img_info_command = ["qemu-img", "info", image_full_path]
        qemu_img_convert_command = ["qemu-img", "convert", "-f", "qcow2", "-O", "raw", image_full_path, f"image.raw"]

        image_import_command = ["rbd", "import", "image.raw", f"{image_store_pool}/{image_uuid}"]
        snapshot_creation_command = ["rbd", "snap", "create", f"{image_store_pool}/{image_uuid}@protected"]
        snapshot_protect_command = ["rbd", "snap", "protect", f"{image_store_pool}/{image_uuid}@protected"]

        if WITHOUT_CEPH:
            image_import_command = ["mv", "image.raw", os.path.join("/var/image", image_uuid)]
            snapshot_creation_command = ["true"]
            snapshot_protect_command = ["true"]

        # First check whether the image is qcow2
        # This would also check whether the file exists or not
        try:
            qemu_img_info = subprocess.Popen(qemu_img_info_command,
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.DEVNULL)
        except Exception as e:
            # Command itself failed i.e maybe qemu-img not found
            # Maybe Popen crashes some other ways
            logging.exception(e)
        else:
            # At least we run the qemu-img info command
            # It may have not executed successfully. If thats
            # the case, our next command grep would also fail
            try:
                # Fetching the lines containing "file format"
                command = ["grep", "-e", "file format"]
                output = subprocess.check_output(command, stdin=qemu_img_info.stdout)
            except Exception as e:
                logging.exception(e)
            else:
                # grep command runs successfully, it implies
                # the previous command qemu-img would have
                # run successfully
                output = output.decode("utf-8").strip()
                if "qcow2" in output:
                    try:
                        # Convert .qcow2 to .raw
                        subprocess.check_output(qemu_img_convert_command)
                    except Exception as e:
                        logging.exception(e)
                    else:
                        # Image successfully converted
                        try:
                            # Import image either to ceph/filesystem
                            subprocess.check_output(image_import_command)
                        except Exception as e:
                            logging.exception(e)
                        else:
                            # Image imported successfully
                            try:
                                subprocess.check_output(snapshot_creation_command)
                                subprocess.check_output(snapshot_protect_command)
                            except Exception as e:
                                logging.exception(e)
                            else:
                                # Everything is successfully done
                                image.value["status"] = "CREATED"
                                client.put(image.key, json.dumps(image.value))
                else:
                    # The user provided image is not in qcow2 format
                    image.value["status"] = "INVALID_FORMAT"
                    client.put(image.key, json.dumps(image.value))

    try:
        os.remove("image.raw")
    except Exception:
        pass