a6ac8ce1db
* Save the size of the guest before running a backup * Display the size in the backup GET/LIST views * Simplify the dbaas module removing redundant class. * Switch get_filesystem_volume_stats to use os.statvfs() * Change output of volume stats to return used in GB to simplify various view that display it. Implements: Blueprint backup-volume-size Change-Id: I860427d3491acb34e43ee23f91e4ffbb39e0042c
144 lines
5.7 KiB
Python
144 lines
5.7 KiB
Python
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
import logging
|
|
from trove.backup.models import DBBackup
|
|
from trove.backup.models import BackupState
|
|
from trove.common import cfg, utils
|
|
from trove.guestagent.dbaas import get_filesystem_volume_stats
|
|
from trove.guestagent.manager.mysql_service import ADMIN_USER_NAME
|
|
from trove.guestagent.manager.mysql_service import get_auth_password
|
|
from trove.guestagent.strategies.backup.base import BackupError
|
|
from trove.guestagent.strategies.backup.base import UnknownBackupType
|
|
from trove.guestagent.strategies.storage import get_storage_strategy
|
|
from trove.guestagent.strategies.backup import get_backup_strategy
|
|
from trove.guestagent.strategies.restore import get_restore_strategy
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
CONF = cfg.CONF
|
|
|
|
RUNNER = get_backup_strategy(CONF.backup_strategy,
|
|
CONF.backup_namespace)
|
|
BACKUP_CONTAINER = CONF.backup_swift_container
|
|
|
|
|
|
class BackupAgent(object):
|
|
|
|
def _get_restore_runner(self, backup_type):
|
|
"""Returns the RestoreRunner associated with this backup type."""
|
|
try:
|
|
runner = get_restore_strategy(backup_type, CONF.restore_namespace)
|
|
except ImportError:
|
|
raise UnknownBackupType("Unknown Backup type: %s" % backup_type)
|
|
return runner
|
|
|
|
def execute_backup(self, context, backup_id, runner=RUNNER):
|
|
LOG.debug("Searching for backup instance %s", backup_id)
|
|
backup = DBBackup.find_by(id=backup_id)
|
|
LOG.info("Setting task state to %s for instance %s",
|
|
BackupState.NEW, backup.instance_id)
|
|
backup.state = BackupState.NEW
|
|
backup.save()
|
|
|
|
LOG.info("Running backup %s", backup_id)
|
|
user = ADMIN_USER_NAME
|
|
password = get_auth_password()
|
|
swiftStorage = get_storage_strategy(
|
|
CONF.storage_strategy,
|
|
CONF.storage_namespace)(context)
|
|
|
|
# Store the size of the filesystem before the backup.
|
|
stats = get_filesystem_volume_stats(CONF.mount_point)
|
|
backup.size = stats.get('used', 0.0)
|
|
backup.state = BackupState.BUILDING
|
|
backup.save()
|
|
|
|
try:
|
|
with runner(filename=backup_id, user=user, password=password)\
|
|
as bkup:
|
|
LOG.info("Starting Backup %s", backup_id)
|
|
success, note, checksum, location = swiftStorage.save(
|
|
BACKUP_CONTAINER,
|
|
bkup)
|
|
|
|
LOG.info("Backup %s completed status: %s", backup_id, success)
|
|
LOG.info("Backup %s file size: %s", backup_id, bkup.content_length)
|
|
LOG.info('Backup %s file checksum: %s', backup_id, checksum)
|
|
LOG.info('Backup %s location: %s', backup_id, location)
|
|
|
|
if not success:
|
|
raise BackupError(backup.note)
|
|
|
|
except Exception as e:
|
|
LOG.error(e)
|
|
LOG.error("Error saving %s Backup", backup_id)
|
|
backup.state = BackupState.FAILED
|
|
backup.save()
|
|
raise
|
|
|
|
else:
|
|
LOG.info("Saving %s Backup Info to model", backup_id)
|
|
backup.state = BackupState.COMPLETED
|
|
backup.checksum = checksum
|
|
backup.location = location
|
|
backup.note = note
|
|
backup.backup_type = bkup.backup_type
|
|
backup.save()
|
|
|
|
def execute_restore(self, context, backup_id, restore_location):
|
|
|
|
try:
|
|
LOG.debug("Cleaning out restore location: %s", restore_location)
|
|
utils.execute_with_timeout("sudo", "chmod", "-R",
|
|
"0777", restore_location)
|
|
utils.clean_out(restore_location)
|
|
|
|
LOG.debug("Finding backup %s to restore", backup_id)
|
|
backup = DBBackup.find_by(id=backup_id)
|
|
|
|
LOG.debug("Getting Restore Runner of type %s", backup.backup_type)
|
|
restore_runner = self._get_restore_runner(backup.backup_type)
|
|
|
|
LOG.debug("Getting Storage Strategy")
|
|
storage_strategy = get_storage_strategy(
|
|
CONF.storage_strategy,
|
|
CONF.storage_namespace)(context)
|
|
|
|
LOG.debug("Preparing storage to download stream.")
|
|
download_stream = storage_strategy.load(context,
|
|
backup.location,
|
|
restore_runner.is_zipped)
|
|
|
|
with restore_runner(restore_stream=download_stream,
|
|
restore_location=restore_location) as runner:
|
|
LOG.debug("Restoring instance from backup %s to %s",
|
|
backup_id, restore_location)
|
|
content_size = runner.restore()
|
|
LOG.info("Restore from backup %s completed successfully to %s",
|
|
backup_id, restore_location)
|
|
LOG.info("Restore size: %s", content_size)
|
|
|
|
utils.execute_with_timeout("sudo", "chown", "-R",
|
|
"mysql", restore_location)
|
|
|
|
except Exception as e:
|
|
LOG.error(e)
|
|
LOG.error("Error restoring backup %s", backup_id)
|
|
raise
|
|
|
|
else:
|
|
LOG.info("Restored Backup %s", backup_id)
|