def get_connection(self): ret = None if self._cross_account_number and self._cross_account_role: self._info( subject=_status.parse_status('cross_account_connect', (self._cross_account_number, self._cross_account_role, self._region)), src_account=self._cross_account_number, src_role=self._cross_account_role, category='connection') from boto.sts import STSConnection import boto try: role_arn = 'arn:aws:iam::%s:role/%s' % (self._cross_account_number, self._cross_account_role) sts = STSConnection() assumed_role = sts.assume_role(role_arn=role_arn, role_session_name='AssumeRoleSession') ret = ec2.connect_to_region( self._region, aws_access_key_id=assumed_role.credentials.access_key, aws_secret_access_key=assumed_role.credentials.secret_key, security_token=assumed_role.credentials.session_token ) except BotoServerError, e: raise BackupMonkeyException('%s: %s' % (_status.parse_status('cross_account_error'), e.message), subject=_status.parse_status('cross_account_error'), body=e.message, src_account=self._cross_account_number, src_role=self._cross_account_role, category='connection')
def get_all_volumes(self, **kwargs): try: return self._conn.get_all_volumes(**kwargs) except BotoServerError, e: raise BackupMonkeyException('%s: %s' % (_status.parse_status('volumes_fetch_error', self._region), e.message), subject=_status.parse_status('volumes_fetch_error', self._region), body=e.message, category='volumes')
def remove_old_snapshots(self): ''' Loop through this account's snapshots, and remove the oldest ones where there are more snapshots per volume than required ''' log.info('Configured to keep %d snapshots per volume', self._snapshots_per_volume) self._info( subject=_status.parse_status('snapshots_fetch', self._region), category='snapshots') try: snapshots = self._conn.get_all_snapshots(owner='self') except BotoServerError, e: raise BackupMonkeyException('%s: %s' % (_status.parse_status('snapshot_fetch_error', self._region), e.message), subject=_status.parse_status('snapshot_fetch_error', self._region), body=e.message, category='snapshots')
def get_filters(self): filters = None try: filters = dict([t.split(':') for t in self._tags]) for f in filters.keys(): try: filters[f] = eval(filters[f]) except Exception: pass except ValueError, e: raise BackupMonkeyException('%s: %s' % (_status.parse_status('tags_invalid'), str(e)), subject=_status.parse_status('tags_invalid'), body=str(e), src_tags=' '.join(self._tags), category='parameters')
def snapshot_volumes(self): ''' Loops through all EBS volumes and creates snapshots of them ''' log.info('Getting list of EBS volumes') volumes = self.get_volumes_to_snapshot() log.info('Found %d volumes', len(volumes)) for volume in volumes: description_parts = [self._prefix] description_parts.append(volume.id) if volume.attach_data.instance_id: description_parts.append(volume.attach_data.instance_id) if volume.attach_data.device: description_parts.append(volume.attach_data.device) description = ' '.join(description_parts) self._info(subject=_status.parse_status('snapshot_create', (volume.id, description)), src_volume=volume.id, src_tags=' '.join([':'.join(i) for i in volume.tags.items()]), category='snapshots') try: snapshot = self._retryInCaseOfException( volume.create_snapshot, description, src_volume=volume.id, category='snapshots', type='alert', severity='high') if volume.tags: snapshot.add_tags(self.remove_reserved_tags(volume.tags)) self._info(subject=_status.parse_status('snapshot_create_success', (snapshot.id, volume.id)), src_volume=volume.id, src_snapshot=snapshot.id, src_tags=' '.join([':'.join(i) for i in snapshot.tags.items()]), category='snapshots') except BotoServerError, e: if e.code == 'SnapshotLimitExceeded': raise BackupMonkeyException('%s: %s' % (_status.parse_status('snapshot_create_error', volume.id), e.message), subject=_status.parse_status('snapshot_create_error', volume.id), body=e.message, src_volume=volume.id, src_tags=' '.join([':'.join(i) for i in self.remove_reserved_tags(volume.tags).items()]), category='snapshots') else: log.error('%s: %s' % (_status.parse_status('snapshot_create_error', volume.id), e.message)) SplunkLogging.write( subject=_status.parse_status('snapshot_create_error', volume.id), body=e.message, src_volume=volume.id, src_tags=' '.join([':'.join(i) for i in self.remove_reserved_tags(volume.tags).items()]), category='snapshots', type='alarm', severity='critical')
def _retryInCaseOfException(self, func, *args, **kwargs): '''Retry with sleep in case of RequestLimitExceeded exception''' result = None for attempt in range(1, 6): try: result = func(*args) except BotoServerError, e: sleep_time = attempt + 5 log.error("Encountered Error %s on %s, waiting %d seconds then retrying", e.message, str(kwargs), sleep_time) splunk_kwargs = { 'subject':_status.parse_status('retry_after_sleep', (str(attempt), str(sleep_time))), 'body':e.message } splunk_kwargs.update(kwargs) SplunkLogging.write(**splunk_kwargs) time.sleep(sleep_time) continue except Exception, e: log.error("Encountered Error %s on %s", e.message, str(kwargs)) raise e
def get_volumes_to_snapshot(self): ''' Returns volumes to snapshot based on passed in tags ''' self._info( subject=_status.parse_status('volumes_fetch', self._region), category='volumes') volumes = [] if self._reverse_tags: filters = self.get_filters() black_list = [] for f in filters.keys(): if isinstance(filters[f], list): black_list = black_list + [(f, i) for i in filters[f]] else: black_list.append((f, filters[f])) for v in self.get_all_volumes(): if len(set(v.tags.items()) - set(black_list)) == len(set(v.tags.items())): volumes.append(v) return volumes else: if self._tags: return self.get_all_volumes(filters=self.get_filters()) else: return self.get_all_volumes()
ret = ec2.connect_to_region( self._region, aws_access_key_id=assumed_role.credentials.access_key, aws_secret_access_key=assumed_role.credentials.secret_key, security_token=assumed_role.credentials.session_token ) except BotoServerError, e: raise BackupMonkeyException('%s: %s' % (_status.parse_status('cross_account_error'), e.message), subject=_status.parse_status('cross_account_error'), body=e.message, src_account=self._cross_account_number, src_role=self._cross_account_role, category='connection') else: self._info( subject=_status.parse_status('region_connect', self._region), category='connection') try: ret = ec2.connect_to_region(self._region) except NoAuthHandlerFound, e: log.critical('No AWS credentials found. To configure Boto, please read: http://boto.readthedocs.org/en/latest/boto_config_tut.html') raise BackupMonkeyException('%s: %s' % (_status.parse_status('region_connect_error'), e.message), subject=_status.parse_status('region_connect_error'), body=e.message, category='connection') if not ret: raise BackupMonkeyException(_status.parse_status('region_connect_invalid', self._region), subject=_status.parse_status('region_connect_invalid', self._region), category='connection') return ret