122 lines
3.8 KiB
Python
122 lines
3.8 KiB
Python
# Copyright 2013 Mirantis, Inc.
|
|
#
|
|
# 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.
|
|
|
|
from collections import deque
|
|
import copy
|
|
import logging
|
|
import time
|
|
|
|
import six
|
|
|
|
from shotgun import settings
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Config(object):
|
|
def __init__(self, data=None):
|
|
self.data = data or {}
|
|
self.time = time.localtime()
|
|
self.offline_hosts = set()
|
|
self.objs = deque()
|
|
self.try_again = deque()
|
|
for properties in six.itervalues(self.data.get('dump', {})):
|
|
hosts = properties.get('hosts') or [{}]
|
|
for obj in properties.get('objects', []):
|
|
for h in hosts:
|
|
obj_new = copy.deepcopy(obj)
|
|
obj_new['host'] = h
|
|
self.objs.append(obj_new)
|
|
|
|
def _timestamp(self, name):
|
|
return "{0}-{1}".format(
|
|
name,
|
|
time.strftime('%Y-%m-%d_%H-%M-%S', self.time)
|
|
)
|
|
|
|
@property
|
|
def target(self):
|
|
target = self.data.get("target", settings.TARGET)
|
|
if self.data.get("timestamp", settings.TIMESTAMP):
|
|
target = self._timestamp(target)
|
|
return target
|
|
|
|
@property
|
|
def compression_level(self):
|
|
level = self.data.get("compression_level")
|
|
if level is None:
|
|
logger.info(
|
|
'Compression level is not specified,'
|
|
' Default %s will be used', settings.COMPRESSION_LEVEL)
|
|
|
|
level = settings.COMPRESSION_LEVEL
|
|
|
|
return '-{level}'.format(level=level)
|
|
|
|
@property
|
|
def lastdump(self):
|
|
return self.data.get("lastdump", settings.LASTDUMP)
|
|
|
|
@staticmethod
|
|
def get_network_address(obj):
|
|
"""Returns network address of object."""
|
|
return obj['host'].get('address') or obj['host'].get('hostname')
|
|
|
|
def on_network_error(self, obj):
|
|
"""Lets the object to have another attempt for being proccessed."""
|
|
host = self.get_network_address(obj)
|
|
logger.debug("Remote host %s is unreachable. "
|
|
"Processing of its objects postponed.", host)
|
|
self.try_again.append(obj)
|
|
self.offline_hosts.add(host)
|
|
|
|
@property
|
|
def objects(self):
|
|
"""Stateful generator for processing objects.
|
|
|
|
It should be used in conjunction with on_network_error() to give
|
|
another try for objects which threw NetworkError.
|
|
"""
|
|
for _ in range(settings.ATTEMPTS):
|
|
while self.objs:
|
|
obj = self.objs.popleft()
|
|
if self.get_network_address(obj) not in self.offline_hosts:
|
|
yield obj
|
|
else:
|
|
self.try_again.append(obj)
|
|
self.offline_hosts.clear()
|
|
self.objs, self.try_again = self.try_again, deque()
|
|
|
|
for obj in self.objs:
|
|
obj["type"] = 'offline'
|
|
host = self.get_network_address(obj)
|
|
if host not in self.offline_hosts:
|
|
self.offline_hosts.add(host)
|
|
yield obj
|
|
else:
|
|
logger.debug("Skipping offline object processing: %s", obj)
|
|
|
|
@property
|
|
def timeout(self):
|
|
"""Timeout for executing commands."""
|
|
return self.data.get("timeout", settings.DEFAULT_TIMEOUT)
|
|
|
|
@property
|
|
def self_log_object(self):
|
|
return {
|
|
"type": "file",
|
|
"path": settings.LOG_FILE
|
|
}
|