Beispiel #1
0
def run():
    parser = argparse.ArgumentParser(description='Loops through all EBS volumes, and snapshots them, then loops through all snapshots, and removes the oldest ones.')
    parser.add_argument('--region', metavar='REGION', 
                        help='the region to loop through and snapshot (default is current region of EC2 instance this is running on). E.g. us-east-1')
    parser.add_argument('--max-snapshots-per-volume', metavar='SNAPSHOTS', default=3, type=int,
                        help='the maximum number of snapshots to keep per EBS volume. The oldest snapshots will be deleted. Default: 3')
    parser.add_argument('--snapshot-only', action='store_true', default=False,
                        help='Only snapshot EBS volumes, do not remove old snapshots')
    parser.add_argument('--remove-only', action='store_true', default=False,
                        help='Only remove old snapshots, do not create new snapshots')
    parser.add_argument('--verbose', '-v', action='count', 
                        help='enable verbose output (-vvv for more)')
    parser.add_argument('--version', action='version', version='%(prog)s ' + __version__,
                        help='display version number and exit')
    args = parser.parse_args()
    
    Logging().configure(args.verbose)

    log.debug("CLI parse args: %s", args)

    if args.region:
        region = args.region
    else:
        # If no region was specified, assume this is running on an EC2 instance
        # and work out what region it is in
        log.debug("Figure out which region I am running in...")
        instance_metadata = get_instance_metadata(timeout=5)
        log.debug('Instance meta-data: %s', instance_metadata)
        if not instance_metadata:
            _fail('Could not determine region. This script is either not running on an EC2 instance (in which case you should use the --region option), or the meta-data service is down')
        
        region = instance_metadata['placement']['availability-zone'][:-1]
        log.debug("Running in region: %s", region)

    try:
        monkey = BackupMonkey(region, args.max_snapshots_per_volume)
        
        if not args.remove_only:
            monkey.snapshot_volumes()
        if not args.snapshot_only:
            monkey.remove_old_snapshots()
        
    except BackupMonkeyException as e:
        _fail(e.message)
    
    log.info('Backup Monkey completed successfully!')
    sys.exit(0)
Beispiel #2
0
class LabelTest(TestCase):

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def setUp(self, mock):
        self.bm = BackupMonkey('us-west-2', 1, [], None, None, None, None)
        self.bm_with_label_daily = BackupMonkey('us-west-2', 1, [], None, 'daily', None, None)
        self.bm_with_label_weekly = BackupMonkey('us-west-2', 1, [], None, 'weekly', None, None)

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_without_label(self, mock):
        snaps = self.bm._conn.get_all_snapshots()
        init_snapshot = filter(lambda x: x.status == 'completed', snaps)
        self.bm.remove_old_snapshots()
        snaps = self.bm._conn.get_all_snapshots()
        end_snapshot = filter(lambda x: x.status == 'completed', snaps)
        assert len(init_snapshot) == 4
        assert len(end_snapshot) == 2

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_with_label_daily(self, mock):
        snaps = self.bm_with_label_daily._conn.get_all_snapshots()
        init_snapshot = filter(lambda x: x.status == 'completed', snaps)
        self.bm_with_label_daily.remove_old_snapshots()
        snaps = self.bm_with_label_daily._conn.get_all_snapshots()
        end_snapshot = filter(lambda x: x.status == 'completed', snaps)
        assert len(init_snapshot) == 4
        assert len(end_snapshot) == 4

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_with_label_weekly(self, mock):
        snaps = self.bm_with_label_weekly._conn.get_all_snapshots()
        init_snapshot = filter(lambda x: x.status == 'completed', snaps)
        self.bm_with_label_weekly.remove_old_snapshots()
        snaps = self.bm_with_label_weekly._conn.get_all_snapshots()
        end_snapshot = filter(lambda x: x.status == 'completed', snaps)
        assert len(init_snapshot) == 4
        assert len(end_snapshot) == 3
Beispiel #3
0
def run():
    parser = argparse.ArgumentParser(
        description=
        'Loops through all EBS volumes, and snapshots them, then loops through all snapshots, and removes the oldest ones.'
    )
    parser.add_argument(
        '--region',
        metavar='REGION',
        help=
        'the region to loop through and snapshot (default is current region of EC2 instance this is running on). E.g. us-east-1'
    )
    parser.add_argument(
        '--max-snapshots-per-volume',
        metavar='SNAPSHOTS',
        default=3,
        type=int,
        help=
        'the maximum number of snapshots to keep per EBS volume. The oldest snapshots will be deleted. Default: 3'
    )
    parser.add_argument(
        '--snapshot-only',
        action='store_true',
        default=False,
        help='Only snapshot EBS volumes, do not remove old snapshots')
    parser.add_argument(
        '--remove-only',
        action='store_true',
        default=False,
        help='Only remove old snapshots, do not create new snapshots')
    parser.add_argument('--verbose',
                        '-v',
                        action='count',
                        help='enable verbose output (-vvv for more)')
    parser.add_argument('--version',
                        action='version',
                        version='%(prog)s ' + __version__,
                        help='display version number and exit')
    args = parser.parse_args()

    Logging().configure(args.verbose)

    log.debug("CLI parse args: %s", args)

    if args.region:
        region = args.region
    else:
        # If no region was specified, assume this is running on an EC2 instance
        # and work out what region it is in
        log.debug("Figure out which region I am running in...")
        instance_metadata = get_instance_metadata(timeout=5)
        log.debug('Instance meta-data: %s', instance_metadata)
        if not instance_metadata:
            _fail(
                'Could not determine region. This script is either not running on an EC2 instance (in which case you should use the --region option), or the meta-data service is down'
            )

        region = instance_metadata['placement']['availability-zone'][:-1]
        log.debug("Running in region: %s", region)

    try:
        monkey = BackupMonkey(region, args.max_snapshots_per_volume)

        if not args.remove_only:
            monkey.snapshot_volumes()
        if not args.snapshot_only:
            monkey.remove_old_snapshots()

    except BackupMonkeyException as e:
        _fail(e.message)

    log.info('Backup Monkey completed successfully!')
    sys.exit(0)
Beispiel #4
0
 def setUp(self, mock):
     self.backup_monkey = BackupMonkey('us-west-2', 3, [], None, None, None, 0)
Beispiel #5
0
class TagsTest(TestCase):

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def setUp(self, mock):
        self.backup_monkey = BackupMonkey('us-west-2', 3, [], None, None, None, 0)

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_instance(self, mock):
        assert isinstance(self.backup_monkey.get_connection(), MockEC2Connection) == True
        assert self.backup_monkey.get_volumes_to_snapshot() == volumes

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_no_tag(self, mock):
        ret = self.backup_monkey.get_volumes_to_snapshot()
        assert len(ret) == 6
        assert ret == volumes 

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_tag(self, mock):
        self.backup_monkey._tags = tag
        ret = self.backup_monkey.get_volumes_to_snapshot()
        assert len(ret) == 2
        assert ret == [match_tag, match_tag_multiple]

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_tag_or(self, mock):
        self.backup_monkey._tags = tag_or
        ret = self.backup_monkey.get_volumes_to_snapshot()
        assert len(ret) == 2 
        assert ret == [match_tag_or_1, match_tag_or_2]

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_tag_multiple(self, mock):
        self.backup_monkey._tags = tag_multiple
        ret = self.backup_monkey.get_volumes_to_snapshot()
        assert len(ret) == 2
        assert ret == [match_tag, match_tag_multiple]

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_tag_reverse_tags(self, mock):
        self.backup_monkey._tags = tag
        self.backup_monkey._reverse_tags = True
        ret = self.backup_monkey.get_volumes_to_snapshot()
        assert len(ret) == 4
        assert ret == [a, match_tag_or_1, b, match_tag_or_2]

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_tag_or_reverse_tags(self, mock):
        self.backup_monkey._tags = tag_or 
        self.backup_monkey._reverse_tags = True
        ret = self.backup_monkey.get_volumes_to_snapshot()
        assert len(ret) == 4 
        assert ret == [a, match_tag, b, match_tag_multiple]

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_tag_multiple_reverse_tags(self, mock):
        self.backup_monkey._tags = tag_multiple
        self.backup_monkey._reverse_tags = True
        ret = self.backup_monkey.get_volumes_to_snapshot()
        assert len(ret) == 4
        assert ret == [a, match_tag_or_1, b, match_tag_or_2]

    @mock.patch('backup_monkey.core.BackupMonkey.get_connection', side_effect=mock_get_connection)
    def test_remove_reserved_tags(self, mock):
        volume_tags = {
            'a': 'a',
            'b': 'b',
            'c': 'c',
            'aws:a': 'aws:a',
            'aws:b': 'aws:b'
        }
        ret = self.backup_monkey.remove_reserved_tags(volume_tags)
        assert len(ret) == 3
        assert ret == { 'a': 'a', 'b': 'b', 'c': 'c' }
Beispiel #6
0
def run():
    parser = argparse.ArgumentParser(
        description=
        'Loops through all EBS volumes, and snapshots them, then loops through all snapshots, and removes the oldest ones.'
    )
    parser.add_argument(
        '--region',
        metavar='REGION',
        help=
        'the region to loop through and snapshot (default is current region of EC2 instance this is running on). E.g. us-east-1'
    )
    parser.add_argument(
        '--max-snapshots-per-volume',
        metavar='SNAPSHOTS',
        default=3,
        type=int,
        help=
        'the maximum number of snapshots to keep per EBS volume. The oldest snapshots will be deleted. Default: 3'
    )
    parser.add_argument(
        '--snapshot-only',
        action='store_true',
        default=False,
        help='Only snapshot EBS volumes, do not remove old snapshots')
    parser.add_argument(
        '--remove-only',
        action='store_true',
        default=False,
        help='Only remove old snapshots, do not create new snapshots')
    parser.add_argument('--verbose',
                        '-v',
                        action='count',
                        help='enable verbose output (-vvv for more)')
    parser.add_argument('--version',
                        action='version',
                        version='%(prog)s ' + __version__,
                        help='display version number and exit')
    parser.add_argument(
        '--tags',
        nargs="+",
        help=
        'Only snapshot instances that match passed in tags. E.g. --tag Name:foo will snapshot all instances with a tag `Name` and value is `foo`'
    )
    parser.add_argument(
        '--reverse-tags',
        action='store_true',
        default=False,
        help=
        'Do a reverse match on the passed in tags. E.g. --tag Name:foo --reverse-tags will snapshot all instances that do not have a `Name` tag with the value `foo`'
    )
    parser.add_argument(
        '--label',
        action='store',
        help=
        'Only snapshot instances that match passed in label are created or deleted. Default: None. Selected all snapshot. You have the posibility of create a different strategies for daily, weekly and monthly for example. Label daily won\'t deleted label weekly'
    )
    parser.add_argument(
        '--cross-account-number',
        action='store',
        help=
        'Do a cross-account snapshot (this is the account number to do snapshots on). NOTE: This requires that you pass in the --cross-account-role parameter. E.g. --cross-account-number 111111111111 --cross-account-role Snapshot'
    )
    parser.add_argument(
        '--cross-account-role',
        action='store',
        help=
        'The name of the role that backup-monkey will assume when doing a cross-account snapshot. E.g. --cross-account-role Snapshot'
    )

    args = parser.parse_args()

    if args.cross_account_number and not args.cross_account_role:
        parser.error(
            'The --cross-account-role parameter is required if you specify --cross-account-number (doing a cross-account snapshot)'
        )

    if args.cross_account_role and not args.cross_account_number:
        parser.error(
            'The --cross-account-number parameter is required if you specify --cross-account-role (doing a cross-account snapshot)'
        )

    if args.reverse_tags and not args.tags:
        parser.error(
            'The --tags parameter is required if you specify --reverse-tags (doing a blacklist filter)'
        )

    if args.label and len(args.label) > LIMIT_LABEL:
        parser.error('The --label parameter lenght should be less than 32')

    Logging().configure(args.verbose)

    log.debug("CLI parse args: %s", args)

    if args.region:
        region = args.region
    else:
        # If no region was specified, assume this is running on an EC2 instance
        # and work out what region it is in
        log.debug("Figure out which region I am running in...")
        instance_metadata = get_instance_metadata(timeout=5)
        log.debug('Instance meta-data: %s', instance_metadata)
        if not instance_metadata:
            _fail(
                'Could not determine region. This script is either not running on an EC2 instance (in which case you should use the --region option), or the meta-data service is down'
            )

        region = instance_metadata['placement']['availability-zone'][:-1]
        log.debug("Running in region: %s", region)

    try:
        monkey = BackupMonkey(region, args.max_snapshots_per_volume, args.tags,
                              args.reverse_tags, args.label,
                              args.cross_account_number,
                              args.cross_account_role)

        if not args.remove_only:
            monkey.snapshot_volumes()
        if not args.snapshot_only:
            monkey.remove_old_snapshots()

    except BackupMonkeyException as e:
        _fail(e.message)

    log.info('Backup Monkey completed successfully!')
    sys.exit(0)
Beispiel #7
0
def run():
    parser = argparse.ArgumentParser(description='Loops through all EBS volumes, and snapshots them, then loops through all snapshots, and removes the oldest ones.')
    parser.add_argument('--region', metavar='REGION', 
                        help='the region to loop through and snapshot (default is current region of EC2 instance this is running on). E.g. us-east-1')
    parser.add_argument('--max-snapshots-per-volume', metavar='SNAPSHOTS', default=3, type=int,
                        help='the maximum number of snapshots to keep per EBS volume. The oldest snapshots will be deleted. Default: 3')
    parser.add_argument('--snapshot-only', action='store_true', default=False,
                        help='Only snapshot EBS volumes, do not remove old snapshots')
    parser.add_argument('--remove-only', action='store_true', default=False,
                        help='Only remove old snapshots, do not create new snapshots')
    parser.add_argument('--snapshot-prefix', action='store', default="BACKUP_MONKEY",
                        help='Created snapshots will contain this prefix. Only considers snapshots for removal that start with this prefix. Default: BACKUP_MONKEY')
    parser.add_argument('--verbose', '-v', action='count', 
                        help='enable verbose output (-vvv for more)')
    parser.add_argument('--version', action='version', version='%(prog)s ' + __version__,
                        help='display version number and exit')
    parser.add_argument('--tags', nargs="+", 
                        help='Only snapshot instances that match passed in tags. E.g. --tag Name:foo will snapshot all instances with a tag `Name` and value is `foo`')
    parser.add_argument('--reverse-tags', action='store_true', default=False,
                        help='Do a reverse match on the passed in tags. E.g. --tag Name:foo --reverse-tags will snapshot all instances that do not have a `Name` tag with the value `foo`')
    parser.add_argument('--label', action='store',
                        help='Only snapshot instances that match passed in label are created or deleted. Default: None. Selected all snapshot. You have the posibility of create a different strategies for daily, weekly and monthly for example. Label daily won\'t deleted label weekly')
    parser.add_argument('--cross-account-number', action='store',
                        help='Do a cross-account snapshot (this is the account number to do snapshots on). NOTE: This requires that you pass in the --cross-account-role parameter. E.g. --cross-account-number 111111111111 --cross-account-role Snapshot')
    parser.add_argument('--cross-account-role', action='store',
                        help='The name of the role that backup-monkey will assume when doing a cross-account snapshot. E.g. --cross-account-role Snapshot')
    parser.add_argument('--path-to-graffiti-config', action='store', 
                        help='backup-monkey can tag all created snapshots by using graffiti-monkey, if this is desired provide the absolute path to the graffiti config')

    args = parser.parse_args()

    if args.cross_account_number and not args.cross_account_role:
        parser.error('The --cross-account-role parameter is required if you specify --cross-account-number (doing a cross-account snapshot)')

    if args.cross_account_role and not args.cross_account_number:
        parser.error('The --cross-account-number parameter is required if you specify --cross-account-role (doing a cross-account snapshot)')

    if args.reverse_tags and not args.tags:
        parser.error('The --tags parameter is required if you specify --reverse-tags (doing a blacklist filter)')

    if args.label and len(args.label) > LIMIT_LABEL:
        parser.error('The --label parameter lenght should be less than 32')

    Logging().configure(args.verbose)

    log.debug("CLI parse args: %s", args)

    if args.region:
        region = args.region
    else:
        # If no region was specified, assume this is running on an EC2 instance
        # and work out what region it is in
        log.debug("Figure out which region I am running in...")
        instance_metadata = get_instance_metadata(timeout=5)
        log.debug('Instance meta-data: %s', instance_metadata)
        if not instance_metadata:
            _fail('Could not determine region. This script is either not running on an EC2 instance (in which case you should use the --region option), or the meta-data service is down')
        
        region = instance_metadata['placement']['availability-zone'][:-1]
        log.debug("Running in region: %s", region)

    try:
        monkey = BackupMonkey(region,
                              args.max_snapshots_per_volume,
                              args.tags,
                              args.reverse_tags,
                              args.label,
                              args.cross_account_number,
                              args.cross_account_role,
                              args.path_to_graffiti_config,
                              args.snapshot_prefix)
        
        if not args.remove_only:
            monkey.snapshot_volumes()
        if not args.snapshot_only:
            monkey.remove_old_snapshots()
        
    except BackupMonkeyException as e:
        _fail(e.message)
    
    log.info('Backup Monkey completed successfully!')
    sys.exit(0)
Beispiel #8
0
 def setUp(self, mock):
     self.bm = BackupMonkey('us-west-2', 1, [], None, None, None, None)
     self.bm_with_label_daily = BackupMonkey('us-west-2', 1, [], None, 'daily', None, None)
     self.bm_with_label_weekly = BackupMonkey('us-west-2', 1, [], None, 'weekly', None, None)