backup.py 6.5 KB
Newer Older
Kristian Feldsam's avatar
Kristian Feldsam committed
1 2 3
#!/usr/bin/env python

import argparse
4 5
import datetime
import time
Kristian Feldsam's avatar
Kristian Feldsam committed
6 7 8 9 10 11 12 13 14 15

import config
import pyone
import functions

# ----------------------------
# Define parser
# ----------------------------
parser = argparse.ArgumentParser(description='OpenNebula Backup Tool')

16 17
parser.add_argument('-i', '--image', help='Image id or comma separated list of image ids to backup. Omit for backup all images', type=functions.list_of_int_arg)
parser.add_argument('-S', '--startImage', help='Image id to start backup from. Backups all following images including defined one', type=int)
18 19 20
parser.add_argument('-a', '--datastore', help='Datastore id or comma separated list of datastore ids to backup from. Omit to backup from all datastores to backup', type=functions.list_of_int_arg)
parser.add_argument('-l', '--label', help='Label or comma separated list of labels of tagged images', type=functions.list_arg)
parser.add_argument('-e', '--exclude', help='Skip (exclude) by label or comma separated list of labels of tagged images', type=functions.list_arg)
21 22 23
parser.add_argument('-P', '--pruneOnly', help='Don\'t backup anything, just prune old backups', action='store_true')
parser.add_argument('-D', '--deployments', help='Not implemented yet! Backup also deployments files from system datastores', action='store_true')
parser.add_argument('-d', '--dryRun', help='Not implemented yet! Dry run - not execute any commands, all cmds will be just printed', action='store_true')
24
parser.add_argument('-v', '--verbose', help='Verbose mode', action='store_true')
Kristian Feldsam's avatar
Kristian Feldsam committed
25 26 27 28 29 30 31 32 33 34 35

# -------------------------------------
# Parse args and proceed with execution
# -------------------------------------
args = parser.parse_args()

# -----------------------
# Connect to OpenNebula
# -----------------------
one = pyone.OneServer(config.ONE['address'], session='%s:%s' % (config.ONE['username'], config.ONE['password']))

36 37 38 39
datastores = functions.prepare_datastores(one, args)
all_images = functions.prepare_images(one, args)
images = functions.filter_images(all_images, datastores, args)

40 41 42 43
# connect and login to 3PAR
from drivers import _3par
_3par.login()

44
# starting backup
45 46
if not args.pruneOnly:
    functions.send_email('Backup started! Images count: %d' % len(images))
47

48
for key, image in sorted(images.iteritems()):
49
    datastore = datastores[image.DATASTORE_ID]
50

51 52
    # only datastores with 3PAR transfer manager
    if datastore.TM_MAD != '3par':
53 54
        continue

55 56 57 58 59 60 61 62 63
    # prune only?
    if args.pruneOnly:
        try:
            _3par.prune(image, args.verbose)
        except Exception as ex:
            print ex
            functions.send_email('Error prune image %d:%s: "%s"' % (image.ID, image.NAME, ex))
        continue

64 65 66 67
    # mark start of backup in verbose output
    if args.verbose:
        print '#============================================================'

68
    # set info abut backup start to image template
69 70 71 72 73 74
    try:
        one.image.update(image.ID, 'BACKUP_IN_PROGRESS=YES BACKUP_FINISHED_UNIX=--- BACKUP_FINISHED_HUMAN=--- BACKUP_STARTED_UNIX=%d BACKUP_STARTED_HUMAN="%s"' % (int(time.time()), datetime.datetime.now().ctime()), 1)
    except Exception as ex:
        print ex
        functions.send_email('Error backup image %d:%s: "%s"' % (image.ID, image.NAME, ex))
        continue
75 76 77 78 79 80 81

    # lock image
    if config.LOCK_RESOURCES:
        if args.verbose:
            print 'Locking image %d:%s' % (image.ID, image.NAME)
        one.image.lock(image.ID, 4)

82 83 84 85 86 87 88 89
    # persistent and attached to VM
    if image.PERSISTENT == 1 and image.RUNNING_VMS > 0:
        vmId = image.VMS.ID[0]
        vm = one.vm.info(vmId)
        vmDiskId = None

        if isinstance(vm.TEMPLATE.get('DISK'), list):
            for vmDisk in vm.TEMPLATE.get('DISK'):
90 91
                # volatile disks doesn't have IMAGE_ID attribute
                if vmDisk.get('IMAGE_ID') is not None and int(vmDisk.get('IMAGE_ID')) == image.ID:
92 93 94 95 96 97 98 99
                    vmDiskId = int(vmDisk.get('DISK_ID'))
                    break
        else:
            vmDiskId = int(vm.TEMPLATE.get('DISK').get('DISK_ID'))

        if vmDiskId is None:
            # error
            print 'Can not found VM Disk ID for image %d:%s attached to VM %d:%s' % (image.ID, image.NAME, vmId, vm.NAME)
100
            functions.send_email('Can not found VM Disk ID for image %d:%s attached to VM %d:%s' % (image.ID, image.NAME, vmId, vm.NAME))
101 102 103 104 105
            continue

        if args.verbose:
            print 'Backup persistent image %d:%s attached to VM %d:%s as disk %d' % (image.ID, image.NAME, vmId, vm.NAME, vmDiskId)

Kristian Feldsam's avatar
Kristian Feldsam committed
106 107 108 109 110 111
        # lock VM
        if config.LOCK_RESOURCES:
            if args.verbose:
                print 'Locking VM %d:%s' % (vmId, vm.NAME)
            one.vm.lock(vmId, 4)

112
        try:
113
            _3par.backup_live(one, image, vm, vmDiskId, args.verbose)
114 115
        except Exception as ex:
            print ex
116
            functions.send_email('Error backup image %d:%s: "%s"' % (image.ID, image.NAME, ex))
117 118
            continue

Kristian Feldsam's avatar
Kristian Feldsam committed
119 120 121 122 123 124
        # unlock VM
        if config.LOCK_RESOURCES:
            if args.verbose:
                print 'Unlocking VM %d:%s' % (vmId, vm.NAME)
            one.vm.unlock(vmId)

125 126 127 128 129
    # persistent not attached
    elif image.PERSISTENT == 1:
        if args.verbose:
            print 'Backup persistent not attached image %d:%s' % (image.ID, image.NAME)

130 131 132 133
        try:
            _3par.backup(image, args.verbose)
        except Exception as ex:
            print ex
134
            functions.send_email('Error backup image %d:%s: "%s"' % (image.ID, image.NAME, ex))
135 136
            continue

137 138 139 140 141
    # non-persistent
    elif image.PERSISTENT == 0:
        if args.verbose:
            print 'Backup non-persistent image %d:%s' % (image.ID, image.NAME)

142 143 144 145
        try:
            _3par.backup(image, args.verbose)
        except Exception as ex:
            print ex
146
            functions.send_email('Error backup image %d:%s: "%s"' % (image.ID, image.NAME, ex))
147 148
            continue

149 150 151 152 153 154 155 156
    # unlock image
    if config.LOCK_RESOURCES:
        if args.verbose:
            print 'Unlocking image %d:%s' % (image.ID, image.NAME)
        one.image.unlock(image.ID)

    # set info abut backup start to image template
    one.image.update(image.ID, 'BACKUP_IN_PROGRESS=NO BACKUP_FINISHED_UNIX=%d BACKUP_FINISHED_HUMAN="%s"' % (int(time.time()), datetime.datetime.now().ctime()), 1)
Kristian Feldsam's avatar
Kristian Feldsam committed
157

158 159 160 161
    # mark end of backup in verbose output
    if args.verbose:
        print '#============================================================'

162 163 164 165 166 167 168
# show borgbackup info
if args.verbose:
    try:
        print functions.borgbackup_info()
    except Exception as ex:
        print ex

169 170
# disconnect form 3PAR
_3par.logout()