davidban77 / gns3fy

Python library wrapper around GNS3 Server REST API
https://davidban77.github.io/gns3fy/
57 stars 28 forks source link

Upload image #63

Closed skeiffer closed 4 years ago

skeiffer commented 4 years ago

Added method to upload images to a GNS3 compute server. Primary use case is to facilitate the upload of bootstrap iso and img files.

Example of use (snip from ansible module):

def md5_for_file(file_name, block_size=2**20):
    """
    Gets MD5 of file
    """
    with open(file_name, "rb") as f:
        md5 = hashlib.md5()
        while True:
            data = f.read(block_size)
            if not data:
                break
            md5.update(data)
        return md5.hexdigest()

def check_existing_file(file_path, server, emulator):
    """
    Checks server for existing file and validates hash
    """

    # Get file hash
    md5sum = md5_for_file(file_path)

    # Get existing images
    existing_images = server.get_compute_images(emulator)

    # Check if file exists and hash matches
    file_name = os.path.basename(file_path)
    return any(i for i in existing_images if i["filename"] == file_name and i["md5sum"] == md5sum)

def main():
    module = AnsibleModule(
        argument_spec=dict(
            url=dict(type="str", required=True),
            port=dict(type="int", default=3080),
            user=dict(type="str", default=None),
            password=dict(type="str", default=None, no_log=True),
            emulator=dict(type="str", default="qemu"),
            file=dict(type="str", required=True)
        )
    )
    if not HAS_GNS3FY:
        module.fail_json(msg=missing_required_lib("gns3fy"), exception=GNS3FY_IMP_ERR)
    result = dict(changed=False, local_compute=None, version=None)
    server_url = module.params["url"]
    server_port = module.params["port"]
    server_user = module.params["user"]
    server_password = module.params["password"]
    emulator = module.params["emulator"]
    file_path = module.params["file"]

    server = Gns3Connector(
        url=f"{server_url}:{server_port}", user=server_user, cred=server_password
    )

    # Validate file exists
    if not os.path.exists(file_path):
        module.fail_json(msg=f"File not found: {file_path}")

    result = dict(changed=False)

    # Check if file exists and hash matches
    existing_file = check_existing_file(file_path, server, emulator)
    if existing_file:
        module.exit_json(**result)

    result["changed"] = True

    if module.check_mode:
        module.exit_json(**result)

    # Upload file
    server.upload_compute_image(emulator, file_path)

    # Look for file post upload
    file_exists_post_upload = check_existing_file(file_path, server, emulator)
    if not file_exists_post_upload:
        module.fail_json(msg="File could not be verified after upload!")

    module.exit_json(**result)  
davidban77 commented 4 years ago

Thanks again for the PR. Will submit a new release soon, in the meantime you can use the develop branch for your work.