BIG-IP File Transfers

Problem this snippet solves:

This python script allows you to transfer files to/from BIG-IP/BIG-IQ. Note that all downloads come from /shared/images, so if you need to download files that are not .iso images, you'll need to copy them to /shared/images and then clean up afterward.

How to use this snippet:

# Download from BIG-IP (Files must be in /shared/images/)

python f_xfer.py download bigip.test.local admin /path/you/want/on/your/system/example.txt


# Upload to BIG-IP (Files placed in /var/config/rest/downloads unless extension is .iso, and then it will be placed in /shared/images/)

python f_xfer.py upload bigip.test.local admin /path/file/exists/on/your/system/example.txt


Code :

import os, requests, argparse, getpass

def _download(host, creds, fp):
    chunk_size = 512 * 1024

    headers = {
        'Content-Type': 'application/octet-stream'
    }
    filename = os.path.basename(fp)
    uri = 'https://%s/mgmt/cm/autodeploy/software-image-downloads/%s' % (host, filename)

    with open(fp, 'wb') as f:
        start = 0
        end = chunk_size - 1
        size = 0
        current_bytes = 0

        while True:
            content_range = "%s-%s/%s" % (start, end, size)
            headers['Content-Range'] = content_range

            #print headers
            resp = requests.get(uri,
                                auth=creds,
                                headers=headers,
                                verify=False,
                                stream=True)

            if resp.status_code == 200:
                # If the size is zero, then this is the first time through the
                # loop and we don't want to write data because we haven't yet
                # figured out the total size of the file.
                if size > 0:
                    current_bytes += chunk_size
                    for chunk in resp.iter_content(chunk_size):
                        f.write(chunk)

                # Once we've downloaded the entire file, we can break out of
                # the loop
                if end == size:
                    break

            crange = resp.headers['Content-Range']

            # Determine the total number of bytes to read
            if size == 0:
                size = int(crange.split('/')[-1]) - 1

                # If the file is smaller than the chunk size, BIG-IP will
                # return an HTTP 400. So adjust the chunk_size down to the
                # total file size...
                if chunk_size > size:
                    end = size

                # ...and pass on the rest of the code
                continue

            start += chunk_size

            if (current_bytes + chunk_size) > size:
                end = size
            else:
                end = start + chunk_size - 1


def _upload(host, creds, fp):

    chunk_size = 512 * 1024
    headers = {
        'Content-Type': 'application/octet-stream'
    }
    fileobj = open(fp, 'rb')
    filename = os.path.basename(fp)
    if os.path.splitext(filename)[-1] == '.iso':
        uri = 'https://%s/mgmt/cm/autodeploy/software-image-uploads/%s' % (host, filename)
    else:
        uri = 'https://%s/mgmt/shared/file-transfer/uploads/%s' % (host, filename)

    size = os.path.getsize(fp)

    start = 0

    while True:
        file_slice = fileobj.read(chunk_size)
        if not file_slice:
            break

        current_bytes = len(file_slice)
        if current_bytes < chunk_size:
            end = size
        else:
            end = start + current_bytes

        content_range = "%s-%s/%s" % (start, end - 1, size)
        headers['Content-Range'] = content_range
        requests.post(uri,
                      auth=creds,
                      data=file_slice,
                      headers=headers,
                      verify=False)

        start += current_bytes


if __name__ == "__main__":
    import os, requests, argparse, getpass
    requests.packages.urllib3.disable_warnings()

    parser = argparse.ArgumentParser(description='Transfer files to/from BIG-IP')

    parser.add_argument("transfer_status", help='upload | download')
    parser.add_argument("host", help='BIG-IP IP or Hostname', )
    parser.add_argument("username", help='BIG-IP Username')
    parser.add_argument("filepath", help='Appropriate Src/Dest Filename with Absolute Path')
    args = vars(parser.parse_args())

    tstat = args['transfer_status']
    hostname = args['host']
    username = args['username']
    filepath = args['filepath']

    print('{}, enter your password: '.format(args['username']))
    password = getpass.getpass()

    if tstat == 'upload':
        _upload(hostname, (username, password), filepath)
    elif tstat == 'download':
        _download(hostname, (username, password), filepath)

Tested this on version:

13.0
Published Jun 25, 2019
Version 1.0
No CommentsBe the first to comment