Refactoring of code:

1) new snapshot module with code vss,
lvm and part of backup.py -
create_snapshot and remove_snapshot

This module should contain all code related shadow,
vss and any new snapshots.

2) new openstack module with code from osclient,
restore and backup (BackupOS)

This module should contain code related to cinder/nova backups

3) new utils module with code from utils, win_utils,
bandwidth, config, exec_cmd, validator, streaming

This module should containd code related to anything
that cannot be extracted to its own module

4) new test modules - snapshot, utils, openstack and apiclient.

Test scheduler daemon is now located in scheduler module.

5) Backup.py is deleted and code placed to
openstack.backup (BackupOS) and to job.BackupJob

Change-Id: I46194b40b3a65c15b6095cfb7388dcfd30d95997
This commit is contained in:
eldar nugaev 2016-03-04 11:45:38 +00:00 committed by Fausto Marzi
parent ee97dbf49a
commit c01d7c0a72
64 changed files with 423 additions and 372 deletions

View File

@ -29,7 +29,7 @@ from freezer.apiclient import backups
from freezer.apiclient import jobs
from freezer.apiclient import registration
from freezer.apiclient import sessions
from freezer.utils import Namespace
from freezer.utils import utils
CONF = cfg.CONF
@ -209,7 +209,7 @@ class Client(object):
# this creates a namespace for self.opts when the client is
# created from other method rather than command line arguments.
if self.opts is None:
self.opts = Namespace({})
self.opts = utils.Namespace({})
if token:
self.opts.os_token = token
if username:

View File

@ -23,9 +23,9 @@ import sys
from tempfile import NamedTemporaryFile
from freezer import __version__ as FREEZER_VERSION
from freezer import config as freezer_config
from freezer import utils
from freezer import winutils
from freezer.utils import config as freezer_config
from freezer.utils import utils
from freezer.utils import winutils
CONF = cfg.CONF

View File

@ -18,11 +18,12 @@ Freezer general utils functions
import multiprocessing
import time
from freezer import streaming
from freezer import utils
from oslo_config import cfg
from oslo_log import log
from freezer.utils import streaming
from freezer.utils import utils
CONF = cfg.CONF
logging = log.getLogger(__name__)

View File

@ -15,8 +15,7 @@ limitations under the License.
Freezer Tar related functions
"""
from freezer import utils
from freezer.utils import get_executable_path
from freezer.utils import utils
class TarCommandBuilder:
@ -157,7 +156,7 @@ def get_tar_flag_from_algo(compression):
'bzip2': '-j',
'xz': '-J',
}
compression_exec = get_executable_path(compression)
compression_exec = utils.get_executable_path(compression)
if not compression_exec:
raise Exception("[*] Critical Error: [*] {0} executable not found ".
format(compression))

View File

@ -19,12 +19,10 @@ import logging
import os
import subprocess
import sys
import threading
from freezer.engine import engine
from freezer.engine.tar import tar_builders
from freezer import streaming
from freezer import winutils
from freezer.utils import winutils
class TarBackupEngine(engine.BackupEngine):

View File

@ -16,14 +16,16 @@ limitations under the License.
"""
import datetime
import os
from oslo_utils import importutils
import sys
import time
from freezer import backup
from freezer import exec_cmd
from freezer import restore
from freezer import utils
from freezer.openstack import backup
from freezer.openstack import restore
from freezer.snapshot import snapshot
from freezer.utils import exec_cmd
from freezer.utils import utils
from oslo_config import cfg
from oslo_log import log
@ -84,8 +86,7 @@ class BackupJob(Job):
mod_name = 'freezer.mode.{0}.{1}'.format(
self.conf.mode, self.conf.mode.capitalize() + 'Mode')
app_mode = importutils.import_object(mod_name, self.conf)
backup_instance = backup.backup(
self.conf, self.storage, self.engine, app_mode)
backup_instance = self.backup(app_mode)
level = backup_instance.level if backup_instance else 0
@ -110,6 +111,65 @@ class BackupJob(Job):
metadata[field_name] = self.conf.__dict__.get(field_name, '') or ''
return metadata
def backup(self, app_mode):
"""
:type app_mode: freezer.mode.mode.Mode
:return:
"""
backup_media = self.conf.backup_media
time_stamp = utils.DateTime.now().timestamp
self.conf.time_stamp = time_stamp
if backup_media == 'fs':
app_mode.prepare()
snapshot_taken = snapshot.snapshot_create(self.conf)
if snapshot_taken:
app_mode.release()
try:
filepath = '.'
chdir_path = os.path.expanduser(
os.path.normpath(self.conf.path_to_backup.strip()))
if not os.path.isdir(chdir_path):
filepath = os.path.basename(chdir_path)
chdir_path = os.path.dirname(chdir_path)
os.chdir(chdir_path)
hostname_backup_name = self.conf.hostname_backup_name
backup_instance = self.storage.create_backup(
hostname_backup_name,
self.conf.no_incremental,
self.conf.max_level,
self.conf.always_level,
self.conf.restart_always_level,
time_stamp=time_stamp)
self.engine.backup(filepath, backup_instance)
return backup_instance
finally:
# whether an error occurred or not, remove the snapshot anyway
app_mode.release()
if snapshot_taken:
snapshot.snapshot_remove(
self.conf, self.conf.shadow,
self.conf.windows_volume)
backup_os = backup.BackupOs(self.conf.client_manager,
self.conf.container,
self.storage)
if backup_media == 'nova':
logging.info('[*] Executing nova backup')
backup_os.backup_nova(self.conf.nova_inst_id)
elif backup_media == 'cindernative':
logging.info('[*] Executing cinder backup')
backup_os.backup_cinder(self.conf.cindernative_vol_id)
elif backup_media == 'cinder':
logging.info('[*] Executing cinder snapshot')
backup_os.backup_cinder_by_glance(self.conf.cinder_vol_id)
else:
raise Exception('unknown parameter backup_media %s' % backup_media)
return None
class RestoreJob(Job):
@Job.executemethod

View File

@ -17,24 +17,26 @@ Freezer main execution function
"""
import json
import os
from oslo_config import cfg
from oslo_log import log
import subprocess
import sys
from freezer import bandwidth
from oslo_config import cfg
from oslo_log import log
from freezer.common import config as freezer_config
from freezer import config
from freezer.engine.tar import tar_engine
from freezer import job
from freezer import osclients
from freezer.openstack import openstack
from freezer.openstack import osclients
from freezer.storage import local
from freezer.storage import multiple
from freezer.storage import ssh
from freezer.storage import swift
from freezer import utils
from freezer import validator
from freezer import winutils
from freezer.utils import bandwidth
from freezer.utils import config
from freezer.utils import utils
from freezer.utils import validator
from freezer.utils import winutils
CONF = cfg.CONF
LOG = log.getLogger(__name__)
@ -43,29 +45,12 @@ LOG = log.getLogger(__name__)
def freezer_main(backup_args):
"""Freezer main loop for job execution.
"""
def set_max_process_priority():
""" Set freezer in max priority on the os """
# children processes inherit niceness from father
try:
LOG.warning(
'[*] Setting freezer execution with high CPU and I/O priority')
PID = os.getpid()
# Set cpu priority
os.nice(-19)
# Set I/O Priority to Real Time class with level 0
subprocess.call([
u'{0}'.format(utils.find_executable("ionice")),
u'-c', u'1', u'-n', u'0', u'-t',
u'-p', u'{0}'.format(PID)
])
except Exception as priority_error:
LOG.warning('[*] Priority: {0}'.format(priority_error))
if not backup_args.quiet:
LOG.info('log file at {0}'.format(CONF.get('log_file')))
if backup_args.max_priority:
set_max_process_priority()
utils.set_max_process_priority()
bandwidth.monkeypatch_socket_bandwidth(backup_args)
@ -156,10 +141,10 @@ def storage_from_dict(backup_args, work_dir, max_segment_size,
container = backup_args['container']
if storage_name == "swift":
if "osrc" in backup_args:
options = utils.OpenstackOptions.create_from_dict(
options = openstack.OpenstackOptions.create_from_dict(
parse_osrc(backup_args['osrc']))
else:
options = utils.OpenstackOptions.create_from_env()
options = openstack.OpenstackOptions.create_from_env()
identity_api_version = (os_identity_api_version or
options.identity_api_version)
client_manager = osclients.ClientManager(
@ -195,10 +180,5 @@ def main():
CONF.print_help()
sys.exit(1)
freezer_main(backup_args)
except ValueError as err:
return fail(1, err, backup_args.quiet)
except ImportError as err:
return fail(1, err, backup_args.quiet)
except Exception as err:
return fail(1, err, backup_args.quiet)

View File

@ -12,8 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from freezer import config
from freezer.mode import mode
from freezer.utils import config
class MysqlMode(mode.Mode):

View File

@ -14,10 +14,10 @@
import logging
from freezer import config
from freezer.mode import mode
from freezer import utils
from freezer import winutils
from freezer.utils import config
from freezer.utils import utils
from freezer.utils import winutils
class SqlserverMode(mode.Mode):

View File

View File

@ -18,13 +18,11 @@ Freezer Backup modes related functions
import os
import time
from freezer import lvm
from freezer import utils
from freezer import vss
from freezer import winutils
from oslo_config import cfg
from oslo_log import log
from freezer.utils import utils
CONF = cfg.CONF
logging = log.getLogger(__name__)
home = os.path.expanduser("~")
@ -118,99 +116,3 @@ class BackupOs:
cinder = client_manager.get_cinder()
cinder.backups.create(volume_id, self.container, name, description,
incremental=True, force=True)
def snapshot_create(backup_opt_dict):
"""
Calls the code to take fs snapshots, depending on the platform
:param backup_opt_dict:
:return: boolean value, True if snapshot has been taken, false otherwise
"""
if winutils.is_windows():
if backup_opt_dict.snapshot:
# Create a shadow copy.
backup_opt_dict.shadow_path, backup_opt_dict.shadow = \
vss.vss_create_shadow_copy(backup_opt_dict.windows_volume)
backup_opt_dict.path_to_backup = winutils.use_shadow(
backup_opt_dict.path_to_backup,
backup_opt_dict.windows_volume)
return True
return False
else:
return lvm.lvm_snap(backup_opt_dict)
def snapshot_remove(backup_opt_dict, shadow, windows_volume):
if winutils.is_windows():
# Delete the shadow copy after the backup
vss.vss_delete_shadow_copy(shadow, windows_volume)
else:
# Unmount and remove lvm snapshot volume
lvm.lvm_snap_remove(backup_opt_dict)
def backup(backup_opt_dict, storage, engine, app_mode):
"""
:param backup_opt_dict:
:param storage:
:type storage: freezer.storage.base.Storage
:param engine: Backup Engine
:type engine: freezer.engine.engine.BackupEngine
:type app_mode: freezer.mode.mode.Mode
:return:
"""
backup_media = backup_opt_dict.backup_media
time_stamp = utils.DateTime.now().timestamp
backup_opt_dict.time_stamp = time_stamp
if backup_media == 'fs':
app_mode.prepare()
snapshot_taken = snapshot_create(backup_opt_dict)
if snapshot_taken:
app_mode.release()
try:
filepath = '.'
chdir_path = os.path.expanduser(
os.path.normpath(backup_opt_dict.path_to_backup.strip()))
if not os.path.isdir(chdir_path):
filepath = os.path.basename(chdir_path)
chdir_path = os.path.dirname(chdir_path)
os.chdir(chdir_path)
hostname_backup_name = backup_opt_dict.hostname_backup_name
backup_instance = storage.create_backup(
hostname_backup_name,
backup_opt_dict.no_incremental,
backup_opt_dict.max_level,
backup_opt_dict.always_level,
backup_opt_dict.restart_always_level,
time_stamp=time_stamp)
engine.backup(filepath, backup_instance)
return backup_instance
finally:
# whether an error occurred or not, remove the snapshot anyway
app_mode.release()
if snapshot_taken:
snapshot_remove(backup_opt_dict, backup_opt_dict.shadow,
backup_opt_dict.windows_volume)
backup_os = BackupOs(backup_opt_dict.client_manager,
backup_opt_dict.container,
storage)
if backup_media == 'nova':
logging.info('[*] Executing nova backup')
backup_os.backup_nova(backup_opt_dict.nova_inst_id)
elif backup_media == 'cindernative':
logging.info('[*] Executing cinder backup')
backup_os.backup_cinder(backup_opt_dict.cindernative_vol_id)
elif backup_media == 'cinder':
logging.info('[*] Executing cinder snapshot')
backup_os.backup_cinder_by_glance(backup_opt_dict.cinder_vol_id)
else:
raise Exception('unknown parameter backup_media %s' % backup_media)
return None

View File

@ -0,0 +1,81 @@
"""
(c) Copyright 2015,2016 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.
"""
import os
class OpenstackOptions:
"""
Stores credentials for OpenStack API.
Can be created using
>> create_from_env()
or
>> create_from_dict(dict)
"""
def __init__(self, user_name, tenant_name, project_name, auth_url,
password, identity_api_version, tenant_id=None,
region_name=None, endpoint_type=None, cert=None,
insecure=False, verify=True):
self.user_name = user_name
self.tenant_name = tenant_name
self.auth_url = auth_url
self.password = password
self.tenant_id = tenant_id
self.project_name = project_name
self.identity_api_version = identity_api_version
self.region_name = region_name
self.endpoint_type = endpoint_type
self.cert = cert
self.insecure = insecure
self.verify = verify
if not (self.password and self.user_name and self.auth_url and
(self.tenant_name or self.project_name)):
raise Exception("Please set up in your env:"
"OS_USERNAME, OS_TENANT_NAME/OS_PROJECT_NAME,"
" OS_AUTH_URL, OS_PASSWORD")
@property
def os_options(self):
"""
:return: The OpenStack options which can have tenant_id,
auth_token, service_type, endpoint_type, tenant_name,
object_storage_url, region_name
"""
return {'tenant_id': self.tenant_id,
'tenant_name': self.tenant_name,
'project_name': self.project_name,
'identity_api_version': self.identity_api_version,
'region_name': self.region_name,
'endpoint_type': self.endpoint_type}
@staticmethod
def create_from_env():
return OpenstackOptions.create_from_dict(os.environ)
@staticmethod
def create_from_dict(src_dict):
return OpenstackOptions(
user_name=src_dict.get('OS_USERNAME', None),
tenant_name=src_dict.get('OS_TENANT_NAME', None),
project_name=src_dict.get('OS_PROJECT_NAME', None),
auth_url=src_dict.get('OS_AUTH_URL', None),
identity_api_version=src_dict.get('OS_IDENTITY_API_VERSION',
'2.0'),
password=src_dict.get('OS_PASSWORD', None),
tenant_id=src_dict.get('OS_TENANT_ID', None),
region_name=src_dict.get('OS_REGION_NAME', None),
endpoint_type=src_dict.get('OS_ENDPOINT_TYPE', None),
cert=src_dict.get('OS_CERT', None)
)

View File

@ -17,11 +17,12 @@ import time
from cinderclient import client as cclient
from glanceclient import client as gclient
from novaclient import client as nclient
import swiftclient
from freezer import utils
from oslo_config import cfg
from oslo_log import log
import swiftclient
from freezer.utils import utils
CONF = cfg.CONF
logging = log.getLogger(__name__)
@ -39,7 +40,7 @@ class ClientManager:
"""
Creates manager of connections to swift, nova, glance and cinder
:param options: OpenstackOptions
:type options: freezer.utils.OpenstackOptions
:type options: freezer.openstack.openstack.OpenstackOptions
:param insecure:
:param swift_auth_version:
:param dry_run:

View File

@ -16,10 +16,11 @@ limitations under the License.
Freezer restore modes related functions
"""
from freezer import utils
from oslo_config import cfg
from oslo_log import log
from freezer.utils import utils
CONF = cfg.CONF
logging = log.getLogger(__name__)

View File

@ -20,7 +20,7 @@ import sys
from freezer import __version__ as FREEZER_VERSION
from freezer.apiclient import client as api_client
from freezer import winutils
from freezer.utils import winutils
from oslo_config import cfg
from oslo_log import log

View File

@ -26,7 +26,7 @@ from time import sleep
from freezer.lib.pep3143daemon import DaemonContext
from freezer.lib.pep3143daemon import PidFile
from freezer.utils import create_dir
from freezer.utils import utils
def setup_logging(log_file):
@ -38,7 +38,7 @@ def setup_logging(log_file):
def configure_logging(file_name):
expanded_file_name = os.path.expanduser(file_name)
expanded_dir_name = os.path.dirname(expanded_file_name)
create_dir(expanded_dir_name, do_log=False)
utils.create_dir(expanded_dir_name, do_log=False)
logging.basicConfig(
filename=expanded_file_name,
level=logging.INFO,

View File

@ -29,7 +29,7 @@ from freezer.scheduler import arguments
from freezer.scheduler import scheduler_job
from freezer.scheduler import shell
from freezer.scheduler import utils
from freezer import winutils
from freezer.utils import winutils
if winutils.is_windows():

View File

@ -29,7 +29,7 @@ except Exception:
def pprint(doc):
print(json.dumps(doc, indent=4))
from freezer.utils import create_dir
from freezer.utils import utils as freezer_utils
def do_session_remove_job(client, args):
@ -174,7 +174,7 @@ def do_job_stop(client, args):
def do_job_download(client, args):
create_dir(args.jobs_dir, do_log=True)
freezer_utils.create_dir(args.jobs_dir, do_log=True)
for doc in _job_list(client, args):
fname = os.path.normpath('{0}/job_{1}.conf'.
format(args.jobs_dir, doc['job_id']))

View File

@ -17,8 +17,8 @@ import os
import win32serviceutil
from freezer import utils
from freezer import winutils
from freezer.utils import utils
from freezer.utils import winutils
def setup_logging(log_file):

View File

@ -19,7 +19,7 @@ import win32event
import win32service
import win32serviceutil
from freezer.winutils import set_environment
from freezer.utils import winutils
class PySvc(win32serviceutil.ServiceFramework):
@ -65,7 +65,7 @@ class PySvc(win32serviceutil.ServiceFramework):
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
set_environment(self.home)
winutils.set_environment(self.home)
if os.environ.get('SERVICE_INSECURE'):
self.insecure = True

View File

View File

@ -23,7 +23,7 @@ import subprocess
import uuid
from freezer.common import config as freezer_config
from freezer import utils
from freezer.utils import utils
def lvm_snap_remove(backup_opt_dict):
@ -47,6 +47,36 @@ def lvm_snap_remove(backup_opt_dict):
logging.info('[*] Snapshot volume {0} removed'.format(lv))
def get_vol_fs_type(vol_name):
"""
The argument need to be a full path lvm name i.e. /dev/vg0/var
or a disk partition like /dev/sda1. The returnet value is the
file system type
"""
if os.path.exists(vol_name) is False:
err = '[*] Provided volume name not found: {0} '.format(vol_name)
logging.exception(err)
raise Exception(err)
file_cmd = '{0} -0 -bLs --no-pad --no-buffer --preserve-date \
{1}'.format(utils.find_executable("file"), vol_name)
file_process = subprocess.Popen(
file_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True,
executable=utils.find_executable("bash"))
(file_out, file_err) = file_process.communicate()
file_match = re.search(r'(\S+?) filesystem data', file_out, re.I)
if file_match is None:
err = '[*] File system type not guessable: {0}'.format(file_err)
logging.exception(err)
raise Exception(err)
else:
filesys_type = file_match.group(1)
logging.info('[*] File system {0} found for volume {1}'.format(
filesys_type, vol_name))
return filesys_type.lower().strip()
def lvm_snap(backup_opt_dict):
"""
Checks the provided parameters and create the lvm snapshot if requested
@ -141,7 +171,7 @@ def lvm_snap(backup_opt_dict):
# Guess the file system of the provided source volume and st mount
# options accordingly
filesys_type = utils.get_vol_fs_type(backup_opt_dict.lvm_srcvol)
filesys_type = get_vol_fs_type(backup_opt_dict.lvm_srcvol)
mount_options = '-o {}'.format(backup_opt_dict.lvm_snapperm)
if 'xfs' == filesys_type:
mount_options = ' -onouuid '

View File

@ -0,0 +1,62 @@
"""
(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 Backup modes related functions
"""
import os
from oslo_config import cfg
from oslo_log import log
from freezer.snapshot import lvm
from freezer.snapshot import vss
from freezer.utils import winutils
CONF = cfg.CONF
logging = log.getLogger(__name__)
home = os.path.expanduser("~")
def snapshot_create(backup_opt_dict):
"""
Calls the code to take fs snapshots, depending on the platform
:param backup_opt_dict:
:return: boolean value, True if snapshot has been taken, false otherwise
"""
if winutils.is_windows():
if backup_opt_dict.snapshot:
# Create a shadow copy.
backup_opt_dict.shadow_path, backup_opt_dict.shadow = \
vss.vss_create_shadow_copy(backup_opt_dict.windows_volume)
backup_opt_dict.path_to_backup = winutils.use_shadow(
backup_opt_dict.path_to_backup,
backup_opt_dict.windows_volume)
return True
return False
else:
return lvm.lvm_snap(backup_opt_dict)
def snapshot_remove(backup_opt_dict, shadow, windows_volume):
if winutils.is_windows():
# Delete the shadow copy after the backup
vss.vss_delete_shadow_copy(shadow, windows_volume)
else:
# Unmount and remove lvm snapshot volume
lvm.lvm_snap_remove(backup_opt_dict)

View File

@ -15,8 +15,8 @@
import logging
import os
from freezer import utils
from freezer import winutils
from freezer.utils import utils
from freezer.utils import winutils
def vss_create_shadow_copy(windows_volume):

View File

@ -12,12 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from freezer import utils
import logging
import os
import re
from freezer.utils import utils
class Storage(object):
"""

View File

@ -14,7 +14,7 @@
from freezer.storage import base
from freezer import utils
from freezer.utils import utils
class FsLikeStorage(base.Storage):

View File

@ -20,7 +20,7 @@ import os
import shutil
from freezer.storage import fslike
from freezer import utils
from freezer.utils import utils
class LocalStorage(fslike.FsLikeStorage):

View File

@ -12,11 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from freezer.storage import base
from freezer import streaming
from oslo_config import cfg
from oslo_log import log
from freezer.storage import base
from freezer.utils import streaming
CONF = cfg.CONF
logging = log.getLogger(__name__)

View File

@ -22,7 +22,7 @@ import paramiko
from freezer.storage import fslike
from freezer import utils
from freezer.utils import utils
class SshStorage(fslike.FsLikeStorage):

View File

@ -26,7 +26,8 @@ import pymongo
import re
from glanceclient.common.utils import IterableWithLength
from freezer.storage import swift
from freezer.utils import OpenstackOptions
from freezer.utils import utils
from freezer.openstack import openstack
from freezer.engine.tar import tar_engine
os.environ['OS_REGION_NAME'] = 'testregion'
@ -315,8 +316,8 @@ class BackupOpt1:
self.cindernative_vol_id = ''
self.nova_inst_id = ''
self.lvm_snapperm = 'ro'
self.options = OpenstackOptions.create_from_dict(os.environ)
from freezer.osclients import ClientManager
self.options = openstack.OpenstackOptions.create_from_dict(os.environ)
from freezer.openstack.osclients import ClientManager
from mock import Mock
self.client_manager = ClientManager(None, False, 2, False)
self.client_manager.get_swift = Mock(

View File

View File

@ -12,14 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from freezer import utils
import logging
import os
import re
from six.moves import configparser
from six.moves import cStringIO
from freezer.utils import utils
class Config:

View File

@ -19,79 +19,19 @@ import datetime
import errno
import logging
import os
import re
import subprocess
import sys
import time
from distutils import spawn as distspawn
from functools import wraps
from oslo_config import cfg
from oslo_log import log
from six.moves import configparser
class OpenstackOptions:
"""
Stores credentials for OpenStack API.
Can be created using
>> create_from_env()
or
>> create_from_dict(dict)
"""
def __init__(self, user_name, tenant_name, project_name, auth_url,
password, identity_api_version, tenant_id=None,
region_name=None, endpoint_type=None, cert=None,
insecure=False, verify=True):
self.user_name = user_name
self.tenant_name = tenant_name
self.auth_url = auth_url
self.password = password
self.tenant_id = tenant_id
self.project_name = project_name
self.identity_api_version = identity_api_version
self.region_name = region_name
self.endpoint_type = endpoint_type
self.cert = cert
self.insecure = insecure
self.verify = verify
if not (self.password and self.user_name and self.auth_url and
(self.tenant_name or self.project_name)):
raise Exception("Please set up in your env:"
"OS_USERNAME, OS_TENANT_NAME/OS_PROJECT_NAME,"
" OS_AUTH_URL, OS_PASSWORD")
@property
def os_options(self):
"""
:return: The OpenStack options which can have tenant_id,
auth_token, service_type, endpoint_type, tenant_name,
object_storage_url, region_name
"""
return {'tenant_id': self.tenant_id,
'tenant_name': self.tenant_name,
'project_name': self.project_name,
'identity_api_version': self.identity_api_version,
'region_name': self.region_name,
'endpoint_type': self.endpoint_type}
@staticmethod
def create_from_env():
return OpenstackOptions.create_from_dict(os.environ)
@staticmethod
def create_from_dict(src_dict):
return OpenstackOptions(
user_name=src_dict.get('OS_USERNAME', None),
tenant_name=src_dict.get('OS_TENANT_NAME', None),
project_name=src_dict.get('OS_PROJECT_NAME', None),
auth_url=src_dict.get('OS_AUTH_URL', None),
identity_api_version=src_dict.get('OS_IDENTITY_API_VERSION',
'2.0'),
password=src_dict.get('OS_PASSWORD', None),
tenant_id=src_dict.get('OS_TENANT_ID', None),
region_name=src_dict.get('OS_REGION_NAME', None),
endpoint_type=src_dict.get('OS_ENDPOINT_TYPE', None),
cert=src_dict.get('OS_CERT', None)
)
CONF = cfg.CONF
LOG = log.getLogger(__name__)
def create_dir_tree(dir):
@ -164,36 +104,6 @@ class DateTime(object):
return DateTime(datetime.datetime.now())
def get_vol_fs_type(vol_name):
"""
The argument need to be a full path lvm name i.e. /dev/vg0/var
or a disk partition like /dev/sda1. The returnet value is the
file system type
"""
if os.path.exists(vol_name) is False:
err = '[*] Provided volume name not found: {0} '.format(vol_name)
logging.exception(err)
raise Exception(err)
file_cmd = '{0} -0 -bLs --no-pad --no-buffer --preserve-date \
{1}'.format(find_executable("file"), vol_name)
file_process = subprocess.Popen(
file_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True,
executable=find_executable("bash"))
(file_out, file_err) = file_process.communicate()
file_match = re.search(r'(\S+?) filesystem data', file_out, re.I)
if file_match is None:
err = '[*] File system type not guessable: {0}'.format(file_err)
logging.exception(err)
raise Exception(err)
else:
filesys_type = file_match.group(1)
logging.info('[*] File system {0} found for volume {1}'.format(
filesys_type, vol_name))
return filesys_type.lower().strip()
def path_join(*args):
"""Should work for windows and linux"""
return "/".join([str(x) for x in args])
@ -361,7 +271,7 @@ def find_executable(name):
def openssl_path():
from freezer import winutils
from freezer.utils import winutils
if winutils.is_windows():
return 'openssl'
else:
@ -370,7 +280,7 @@ def openssl_path():
def tar_path():
"""This function returns tar binary path"""
from freezer import winutils
from freezer.utils import winutils
if winutils.is_windows():
path_to_binaries = os.path.dirname(os.path.abspath(__file__))
return '{0}\\bin\\tar.exe'.format(path_to_binaries)
@ -392,7 +302,7 @@ def get_executable_path(binary):
:rtype: str
:return: Absoulte Path to the executable file
"""
from freezer import winutils
from freezer.utils import winutils
if winutils.is_windows():
path_to_binaries = os.path.dirname(os.path.abspath(__file__))
return '{0}\\bin\\{1}.exe'.format(path_to_binaries, binary)
@ -520,3 +430,22 @@ class Namespace(dict):
@staticmethod
def delattr(ns, name):
return object.__delattr__(ns, name)
def set_max_process_priority():
""" Set freezer in max priority on the os """
# children processes inherit niceness from father
try:
LOG.warning(
'[*] Setting freezer execution with high CPU and I/O priority')
PID = os.getpid()
# Set cpu priority
os.nice(-19)
# Set I/O Priority to Real Time class with level 0
subprocess.call([
u'{0}'.format(find_executable("ionice")),
u'-c', u'1', u'-n', u'0', u'-t',
u'-p', u'{0}'.format(PID)
])
except Exception as priority_error:
LOG.warning('[*] Priority: {0}'.format(priority_error))

View File

@ -14,13 +14,10 @@
import ctypes
import json
import logging
import os
import six
import sys
from freezer.utils import create_subprocess
def is_windows():
"""

View File

View File

@ -14,8 +14,9 @@
import unittest
from freezer.engine.tar import tar_builders
from freezer import utils
from freezer.utils import utils
class TestTarCommandBuilder(unittest.TestCase):

View File

View File

@ -16,13 +16,14 @@
import unittest
import mock
from freezer import osclients
from freezer import utils
from freezer.openstack import openstack
from freezer.openstack import osclients
from freezer.utils import utils
class TestOsClients(unittest.TestCase):
fake_options = utils.OpenstackOptions(
fake_options = openstack.OpenstackOptions(
user_name="user", tenant_name="tenant", project_name="project",
auth_url="url", password="password", identity_api_version="3",
insecure=False, cert='cert', verify=True)
@ -43,7 +44,7 @@ class TestOsClients(unittest.TestCase):
client.create_nova()
def test_create_swift_public(self):
options = utils.OpenstackOptions(
options = openstack.OpenstackOptions(
user_name="user", tenant_name="tenant", project_name="project",
auth_url="url", password="password", identity_api_version="3",
endpoint_type="adminURL", insecure=False, cert='cert',
@ -68,4 +69,4 @@ class TestOsClients(unittest.TestCase):
def get_nova(self):
client = osclients.ClientManager(self.fake_options, None, None, None)
client.get_nova()
client.get_nova()

View File

@ -17,7 +17,7 @@ limitations under the License.
"""
import unittest
from freezer import restore
from freezer.openstack import restore
from freezer.tests import commons

View File

@ -28,7 +28,7 @@ class TestLogging(unittest.TestCase):
res = daemon.setup_logging(None)
self.assertEqual('/var/log/freezer-scheduler.log', res)
@patch('freezer.scheduler.daemon.create_dir')
@patch('freezer.utils.utils.create_dir')
@patch('freezer.scheduler.daemon.logging')
def test_setup_logging_userdefined(self, mock_logging, mock_createdir):
res = daemon.setup_logging('mylogfile')

View File

View File

@ -16,16 +16,16 @@ limitations under the License.
"""
import unittest
from mock import Mock, patch, mock_open, call
from mock import Mock, patch
from freezer import lvm
from freezer.snapshot import lvm
class Test_lvm_snap_remove(unittest.TestCase):
@patch('freezer.lvm.os')
@patch('freezer.lvm._umount')
@patch('freezer.lvm._lvremove')
@patch('freezer.snapshot.lvm.os')
@patch('freezer.snapshot.lvm._umount')
@patch('freezer.snapshot.lvm._lvremove')
def test_return_none_on_success(self, mock_lvremove, mock_umount, mock_os):
backup_opt = Mock()
backup_opt.lvm_volgroup = 'one'
@ -35,7 +35,7 @@ class Test_lvm_snap_remove(unittest.TestCase):
class Test_lvm_snap(unittest.TestCase):
@patch('freezer.lvm.validate_lvm_params')
@patch('freezer.snapshot.lvm.validate_lvm_params')
def test_no_lvm_configured_returns_false(self, mock_validate_lvm_params):
backup_opt = Mock()
backup_opt.lvm_auto_snap = ''
@ -43,9 +43,9 @@ class Test_lvm_snap(unittest.TestCase):
backup_opt.snapshot = False
self.assertFalse(lvm.lvm_snap(backup_opt))
@patch('freezer.lvm.validate_lvm_params')
@patch('freezer.lvm.get_lvm_info')
@patch('freezer.lvm.utils.create_dir')
@patch('freezer.snapshot.lvm.validate_lvm_params')
@patch('freezer.snapshot.lvm.get_lvm_info')
@patch('freezer.snapshot.lvm.utils.create_dir')
def test_with_auto_snap_param_path_mismatch_raises(self, mock_create_dir, mock_get_lvm_info, mock_validate_lvm_params):
mock_get_lvm_info.return_value = {
'volgroup': 'lvm_volgroup',
@ -60,8 +60,8 @@ class Test_lvm_snap(unittest.TestCase):
self.assertRaises(Exception, lvm.lvm_snap, backup_opt)
@patch('freezer.lvm.get_lvm_info')
@patch('freezer.lvm.utils.create_dir')
@patch('freezer.snapshot.lvm.get_lvm_info')
@patch('freezer.snapshot.lvm.utils.create_dir')
def test_with_snapshot_opt_simple_sets_correct_path_and_raises_on_perm(self, mock_create_dir, mock_get_lvm_info):
mock_get_lvm_info.return_value = {
'volgroup': 'lvm_volgroup',
@ -81,11 +81,11 @@ class Test_lvm_snap(unittest.TestCase):
self.assertIn('Invalid value for option lvm-snap-perm',
str(the_exception))
@patch('freezer.lvm.validate_lvm_params')
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.lvm.utils.get_vol_fs_type')
@patch('freezer.lvm.get_lvm_info')
@patch('freezer.lvm.utils.create_dir')
@patch('freezer.snapshot.lvm.validate_lvm_params')
@patch('freezer.snapshot.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.get_vol_fs_type')
@patch('freezer.snapshot.lvm.get_lvm_info')
@patch('freezer.snapshot.lvm.utils.create_dir')
def test_ok(self, mock_create_dir, mock_get_lvm_info, mock_get_vol_fs_type, mock_popen, mock_validate_lvm_params):
mock_get_lvm_info.return_value = {
'volgroup': 'lvm_volgroup',
@ -107,11 +107,11 @@ class Test_lvm_snap(unittest.TestCase):
self.assertTrue(lvm.lvm_snap(backup_opt))
@patch('freezer.lvm.validate_lvm_params')
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.lvm.utils.get_vol_fs_type')
@patch('freezer.lvm.get_lvm_info')
@patch('freezer.lvm.utils.create_dir')
@patch('freezer.snapshot.lvm.validate_lvm_params')
@patch('freezer.snapshot.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.get_vol_fs_type')
@patch('freezer.snapshot.lvm.get_lvm_info')
@patch('freezer.utils.utils.create_dir')
def test_snapshot_fails(self, mock_create_dir, mock_get_lvm_info, mock_get_vol_fs_type, mock_popen, mock_validate_lvm_params):
mock_get_lvm_info.return_value = {
'volgroup': 'lvm_volgroup',
@ -134,12 +134,12 @@ class Test_lvm_snap(unittest.TestCase):
the_exception = cm.exception
self.assertIn('lvm snapshot creation error', str(the_exception))
@patch('freezer.lvm.lvm_snap_remove')
@patch('freezer.lvm.validate_lvm_params')
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.lvm.utils.get_vol_fs_type')
@patch('freezer.lvm.get_lvm_info')
@patch('freezer.lvm.utils.create_dir')
@patch('freezer.snapshot.lvm.lvm_snap_remove')
@patch('freezer.snapshot.lvm.validate_lvm_params')
@patch('freezer.snapshot.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.get_vol_fs_type')
@patch('freezer.snapshot.lvm.get_lvm_info')
@patch('freezer.utils.utils.create_dir')
def test_already_mounted(self, mock_create_dir, mock_get_lvm_info, mock_get_vol_fs_type,
mock_popen, mock_validate_lvm_params, lvm_snap_remove):
mock_get_vol_fs_type.return_value = 'xfs'
@ -161,11 +161,11 @@ class Test_lvm_snap(unittest.TestCase):
self.assertTrue(lvm.lvm_snap(backup_opt))
@patch('freezer.lvm.lvm_snap_remove')
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.lvm.utils.get_vol_fs_type')
@patch('freezer.lvm.get_lvm_info')
@patch('freezer.lvm.utils.create_dir')
@patch('freezer.snapshot.lvm.lvm_snap_remove')
@patch('freezer.snapshot.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.get_vol_fs_type')
@patch('freezer.snapshot.lvm.get_lvm_info')
@patch('freezer.snapshot.lvm.utils.create_dir')
def test_snapshot_mount_error_raises_Exception(self,
mock_create_dir,
mock_get_lvm_info,
@ -204,8 +204,8 @@ class Test_lvm_snap(unittest.TestCase):
# class Test_get_lvm_info(unittest.TestCase):
# @patch('freezer.lvm.lvm_guess')
# @patch('freezer.lvm.utils.get_mount_from_path')
# @patch('freezer.snapshot.lvm.lvm_guess')
# @patch('freezer.snapshot.lvm.utils.get_mount_from_path')
# def test_using_guess(self, mock_get_mount_from_path, mock_lvm_guess):
# mock_get_mount_from_path.return_value = '/home/somedir', 'some-snap-path'
# mock_lvm_guess.return_value = 'vg_test', 'lv_test', 'lvm_device'
@ -220,9 +220,9 @@ class Test_lvm_snap(unittest.TestCase):
# 'srcvol': 'lvm_device'}
# self.assertEquals(res, expected_result)
# @patch('freezer.lvm.subprocess.Popen')
# @patch('freezer.lvm.lvm_guess')
# @patch('freezer.lvm.utils.get_mount_from_path')
# @patch('freezer.snapshot.lvm.subprocess.Popen')
# @patch('freezer.snapshot.lvm.lvm_guess')
# @patch('freezer.snapshot.lvm.utils.get_mount_from_path')
# def test_using_mount(self, mock_get_mount_from_path, mock_lvm_guess, mock_popen):
# mock_get_mount_from_path.return_value = '/home/somedir', 'some-snap-path'
# mock_lvm_guess.side_effect = [(None, None, None), ('vg_test', 'lv_test', 'lvm_device')]
@ -241,9 +241,9 @@ class Test_lvm_snap(unittest.TestCase):
# 'srcvol': 'lvm_device'}
# self.assertEquals(res, expected_result)
#
# @patch('freezer.lvm.subprocess.Popen')
# @patch('freezer.lvm.lvm_guess')
# @patch('freezer.lvm.utils.get_mount_from_path')
# @patch('freezer.snapshot.lvm.subprocess.Popen')
# @patch('freezer.snapshot.lvm.lvm_guess')
# @patch('freezer.snapshot.lvm.utils.get_mount_from_path')
# def test_raises_Exception_when_info_not_found(self, mock_get_mount_from_path, mock_lvm_guess, mock_popen):
# mock_get_mount_from_path.return_value = '/home/somedir', 'some-snap-path'
# mock_lvm_guess.return_value = None, None, None
@ -354,7 +354,7 @@ class Test_validate_lvm_params(unittest.TestCase):
class Test_umount(unittest.TestCase):
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.subprocess.Popen')
def test_return_none_on_success(self, mock_popen):
mock_process = Mock()
mock_process.communicate.return_value = '', ''
@ -362,7 +362,7 @@ class Test_umount(unittest.TestCase):
mock_popen.return_value = mock_process
self.assertIsNone(lvm._umount('path'))
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.subprocess.Popen')
def test_raises_on_popen_returncode_not_0(self, mock_popen):
mock_process = Mock()
mock_process.communicate.return_value = '', ''
@ -373,7 +373,7 @@ class Test_umount(unittest.TestCase):
class Test_lvremove(unittest.TestCase):
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.subprocess.Popen')
def test_return_none_on_success(self, mock_popen):
mock_process = Mock()
mock_process.communicate.return_value = '', ''
@ -381,7 +381,7 @@ class Test_lvremove(unittest.TestCase):
mock_popen.return_value = mock_process
self.assertIsNone(lvm._lvremove('logicalvolume'))
@patch('freezer.lvm.subprocess.Popen')
@patch('freezer.snapshot.lvm.subprocess.Popen')
def test_raises_on_popen_returncode_not_0(self, mock_popen):
mock_process = Mock()
mock_process.communicate.return_value = '', ''

View File

@ -12,11 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
import unittest
from freezer.snapshot import vss
from freezer.tests.commons import (FakeDisableFileSystemRedirection, FakeSubProcess,
FakeSubProcess3, FakeSubProcess6)
from freezer import vss
import unittest
import mock
class TestVss(unittest.TestCase):

View File

@ -18,7 +18,7 @@ import shutil
import unittest
from freezer.storage import local
from freezer import utils
from freezer.utils import utils
class TestLocalStorage(unittest.TestCase):

View File

@ -14,8 +14,9 @@
import unittest
from freezer import osclients
from freezer import utils
from freezer.openstack import openstack
from freezer.openstack import osclients
from freezer.storage import swift
from freezer.storage import base
@ -26,7 +27,7 @@ class TestSwiftStorage(unittest.TestCase):
self.storage = swift.SwiftStorage(
osclients.ClientManager(
utils.OpenstackOptions.create_from_env()
openstack.OpenstackOptions.create_from_env()
),
"freezer_ops-aw1ops1-gerrit0001.aw1.hpcloud.net",
"/tmp/",

View File

@ -16,13 +16,14 @@ limitations under the License.
"""
from freezer.tests.commons import *
from freezer.job import ExecJob
from freezer.job import Job, InfoJob, AdminJob, BackupJob
from mock import patch, Mock
import unittest
from freezer.tests.commons import *
from freezer.job import ExecJob
from freezer.job import Job, InfoJob, AdminJob, BackupJob
class TestJob(unittest.TestCase):
def test_execute(self):
@ -71,8 +72,8 @@ class TestExecJob(TestJob):
def setUp(self):
#init mock_popen
self.popen=patch('freezer.exec_cmd.subprocess.Popen')
self.mock_popen=self.popen.start()
self.popen = patch('freezer.utils.exec_cmd.subprocess.Popen')
self.mock_popen = self.popen.start()
self.mock_popen.return_value = Mock()
self.mock_popen.return_value.communicate = Mock()
self.mock_popen.return_value.communicate.return_value = ['some stderr']
@ -91,7 +92,7 @@ class TestExecJob(TestJob):
ExecJob(backup_opt, backup_opt.storage).execute()
def test_execute_raise(self):
self.popen=patch('freezer.exec_cmd.subprocess.Popen')
self.popen=patch('freezer.utils.exec_cmd.subprocess.Popen')
self.mock_popen=self.popen.start()
self.mock_popen.return_value.returncode = 1
backup_opt = BackupOpt1()

View File

View File

@ -13,7 +13,7 @@
# limitations under the License.
import unittest
from freezer import bandwidth
from freezer.utils import bandwidth
class FakeSocket:

View File

@ -14,7 +14,7 @@
import unittest
from freezer import config
from freezer.utils import config
class TestConfig(unittest.TestCase):

View File

@ -11,17 +11,18 @@
# 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.
from freezer import exec_cmd
from mock import patch, Mock
import subprocess
import unittest
from mock import patch, Mock
from freezer.utils import exec_cmd
class TestExec(unittest.TestCase):
def test_exec_cmd(self):
cmd="echo test > test.txt"
popen=patch('freezer.exec_cmd.subprocess.Popen')
popen=patch('freezer.utils.exec_cmd.subprocess.Popen')
mock_popen=popen.start()
mock_popen.return_value = Mock()
mock_popen.return_value.communicate = Mock()
@ -37,7 +38,7 @@ class TestExec(unittest.TestCase):
def test__exec_cmd_with_pipe(self):
cmd="echo test|wc -l"
popen=patch('freezer.exec_cmd.subprocess.Popen')
popen=patch('freezer.utils.exec_cmd.subprocess.Popen')
mock_popen=popen.start()
mock_popen.return_value = Mock()
mock_popen.return_value.communicate = Mock()

View File

@ -16,8 +16,9 @@
import datetime
import unittest
from freezer.openstack import openstack
from freezer.tests.commons import *
from freezer import utils
from freezer.utils import utils
class TestUtils(unittest.TestCase):
@ -70,7 +71,7 @@ class TestUtils(unittest.TestCase):
OS_PASSWORD='testpassword',
OS_REGION_NAME='testregion',
OS_TENANT_ID='0123456789')
options = OpenstackOptions.create_from_dict(env_dict)
options = openstack.OpenstackOptions.create_from_dict(env_dict)
assert options.user_name == env_dict['OS_USERNAME']
assert options.tenant_name == env_dict['OS_TENANT_NAME']
assert options.auth_url == env_dict['OS_AUTH_URL']
@ -82,7 +83,7 @@ class TestUtils(unittest.TestCase):
OS_TENANT_NAME='testtenantename',
OS_AUTH_URL='testauthurl',
OS_PASSWORD='testpassword')
options = OpenstackOptions.create_from_dict(env_dict)
options = openstack.OpenstackOptions.create_from_dict(env_dict)
assert options.user_name == env_dict['OS_USERNAME']
assert options.tenant_name == env_dict['OS_TENANT_NAME']
assert options.auth_url == env_dict['OS_AUTH_URL']

View File

@ -14,8 +14,9 @@
import unittest
from freezer import validator
from freezer import utils
from freezer.utils import validator
from freezer.utils import utils
class TestValidator(unittest.TestCase):
def test_pass(self):

View File

@ -12,14 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from freezer.tests.commons import *
from freezer.winutils import is_windows
from freezer.winutils import use_shadow
from freezer.winutils import DisableFileSystemRedirection
from freezer import winutils
import unittest
import mock
from freezer.tests.commons import *
from freezer.utils import winutils
class TestWinutils(unittest.TestCase):
@ -40,17 +38,17 @@ class TestWinutils(unittest.TestCase):
def test_is_windows(self):
fake_os = Os()
os.name = fake_os
assert is_windows() is False
assert winutils.is_windows() is False
def test_use_shadow(self):
test_volume = 'C:'
test_volume2 = 'C:\\'
path = 'C:\\Users\\Test'
expected = 'C:\\freezer_shadowcopy\\Users\\Test'
assert use_shadow(path, test_volume2) == expected
assert winutils.use_shadow(path, test_volume2) == expected
# test if the volume format is incorrect
self.assertRaises(Exception, use_shadow(path, test_volume))
self.assertRaises(Exception, winutils.use_shadow(path, test_volume))
# def test_start_sql_server(self):
# backup_opt = BackupOpt1()