Increase the fullbackup-rotation for cinder backup

Define fullbackup-rotation for cinder fullbackup,
and delete the fullbackup off limit.

Usage:
freezer-agent --action admin --mode cindernative \
--cindernative-vol-id 111 --fullbackup-rotation 2

Change-Id: Iaa529735d6c6bb5339ececc6fa49f6dc8e975d43
This commit is contained in:
yangyapeng 2017-04-20 15:26:33 +08:00 committed by yapeng
parent 4adfb6b46b
commit 0157b2df50
4 changed files with 122 additions and 1 deletions

View File

@ -506,6 +506,15 @@ _COMMON = [
"this time it will raise a TimeOut Exception. Default is"
" {0}".format(DEFAULT_PARAMS['timeout'])
),
cfg.IntOpt('fullbackup-rotation',
dest='fullbackup_rotation',
default=1,
min=1,
help="Keep the last N fullbackups of cinder-volume, "
"the parameter should be greater than 0. "
"If set action to admin and set the parameter, "
"it should keep the last N fullbackups, "
"other backups should be deleted"),
]

View File

@ -27,6 +27,7 @@ from oslo_log import log
from oslo_utils import importutils
import six
from freezer.openstack import admin
from freezer.openstack import backup
from freezer.openstack import restore
from freezer.snapshot import snapshot
@ -408,12 +409,24 @@ class AdminJob(Job):
def _validate(self):
# no validation required in this job
if not self.conf.remove_from_date and not self.conf.remove_older_than:
if self.conf.backup_media == 'cindernative':
if not self.conf.fullbackup_rotation:
raise Exception("The parameter --fullbackup-rotation "
"is required")
elif not (self.conf.remove_from_date or self.conf.remove_older_than):
raise ValueError("You need to provide to remove backup older "
"than this time. You can use --remove-older-than "
"or --remove-from-date")
def execute(self):
# remove backups by freezer admin action
backup_media = self.conf.backup_media
if backup_media == 'cindernative':
admin_os = admin.AdminOs(self.conf.client_manager)
admin_os.del_off_limit_fullbackup(
self.conf.cindernative_vol_id,
self.conf.fullbackup_rotation)
return {}
if self.conf.remove_from_date:
timestamp = utils.date_to_timestamp(self.conf.remove_from_date)
else:

View File

@ -0,0 +1,98 @@
"""
(c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Freezer Admin modes related functions
"""
import time
from oslo_config import cfg
from oslo_log import log
from oslo_service import loopingcall
CONF = cfg.CONF
LOG = log.getLogger(__name__)
class AdminOs(object):
def __init__(self, client_manager):
"""
:param client_manager:
:return:
"""
self.client_manager = client_manager
self.cinder_client = self.client_manager.get_cinder()
def del_cinderbackup_and_dependend_incremental(self, backup_id):
"""
:param backup_id: backup_id of cinder volume
:return:
"""
cinder_client = self.cinder_client
search_opts = {
'parent_id': backup_id
}
backups = cinder_client.backups.list(search_opts=search_opts)
if backups:
for backup in backups:
self.del_cinderbackup_and_dependend_incremental(backup.id)
LOG.info("preparing to delete backup %s", backup_id)
cinder_client.backups.delete(backup_id)
start_time = int(time.time())
def wait_del_backup():
timeout = 120
del_backup = cinder_client.backups.list(
search_opts={'id': backup_id})
if len(del_backup) == 0:
LOG.info("Delete backup %s complete" % backup_id)
raise loopingcall.LoopingCallDone()
if del_backup[0].status in ['error', 'error_deleting']:
raise Exception("Delete backup %s failed, "
"the status of backup is %s."
% (backup_id, del_backup[0].status))
if (del_backup[0].status == 'deleting') and (int(time.time()) -
start_time > timeout):
LOG.error("Delete backup %s failed, In a state of"
"deleting over 120s")
raise
timer = loopingcall.FixedIntervalLoopingCall(wait_del_backup)
timer.start(interval=0.5).wait()
def del_off_limit_fullbackup(self, volume_id, keep_number):
"""
:param volume_id: id of Volume
:param keep_number: int keep number of fullbackup
:return:
"""
cinder_client = self.cinder_client
search_opts = {
'volume_id': volume_id,
'status': 'available'
}
backups = cinder_client.backups.list(search_opts=search_opts,
sort='created_at:asc')
# Filter fullbackup
fullbackups = [backup for backup in backups
if not backup.is_incremental]
if len(fullbackups) <= keep_number:
LOG.info("The numbers of %s fullbackup is %d,"
"but keep-number-of-fullbackup is %d,"
"don't need delete old backups."
% (volume_id, len(fullbackups), keep_number))
return
for fullbackup in fullbackups[:-keep_number]:
self.del_cinderbackup_and_dependend_incremental(fullbackup.id)

View File

@ -16,6 +16,7 @@ oslo.log>=3.22.0 # Apache-2.0
oslo.config!=4.3.0,!=4.4.0,>=4.0.0 # Apache-2.0
keystoneauth1>=3.1.0 # Apache-2.0
os-brick>=1.15.2 # Apache-2.0
oslo.service>=1.10.0 # Apache-2.0
pycrypto>=2.6 # Public Domain
PyMySQL>=0.7.6 # MIT License