deb-python-shotgun/shotgun/config.py

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
}