|
|
import errno
|
|
|
import sys
|
|
|
import os
|
|
|
|
|
|
from ansible.utils.display import Display
|
|
|
from ansible.utils.color import stringc
|
|
|
from ansible.utils.singleton import Singleton
|
|
|
|
|
|
from .utils import get_ansible_task_log_path
|
|
|
|
|
|
|
|
|
class UnSingleton(Singleton):
|
|
|
def __init__(cls, name, bases, dct):
|
|
|
type.__init__(cls, name, bases, dct)
|
|
|
|
|
|
def __call__(cls, *args, **kwargs):
|
|
|
return type.__call__(cls, *args, **kwargs)
|
|
|
|
|
|
|
|
|
class AdHocDisplay(Display, metaclass=UnSingleton):
|
|
|
def __init__(self, execution_id, verbosity=0):
|
|
|
super().__init__(verbosity=verbosity)
|
|
|
if execution_id:
|
|
|
log_path = get_ansible_task_log_path(execution_id)
|
|
|
else:
|
|
|
log_path = os.devnull
|
|
|
self.log_file = open(log_path, mode='a')
|
|
|
|
|
|
def close(self):
|
|
|
self.log_file.close()
|
|
|
|
|
|
def set_cowsay_info(self):
|
|
|
# 中断 cowsay 的测试,会频繁开启子进程
|
|
|
return
|
|
|
|
|
|
def _write_to_screen(self, msg, stderr):
|
|
|
if not stderr:
|
|
|
screen = sys.stdout
|
|
|
else:
|
|
|
screen = sys.stderr
|
|
|
|
|
|
screen.write(msg)
|
|
|
|
|
|
try:
|
|
|
screen.flush()
|
|
|
except IOError as e:
|
|
|
# Ignore EPIPE in case fileobj has been prematurely closed, eg.
|
|
|
# when piping to "head -n1"
|
|
|
if e.errno != errno.EPIPE:
|
|
|
raise
|
|
|
|
|
|
def _write_to_log_file(self, msg):
|
|
|
# 这里先不 flush,log 文件不需要那么及时。
|
|
|
self.log_file.write(msg)
|
|
|
|
|
|
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False, newline=True):
|
|
|
if log_only:
|
|
|
return
|
|
|
|
|
|
if color:
|
|
|
msg = stringc(msg, color)
|
|
|
|
|
|
if not msg.endswith(u'\n'):
|
|
|
msg2 = msg + u'\n'
|
|
|
else:
|
|
|
msg2 = msg
|
|
|
|
|
|
self._write_to_log_file(msg2)
|
|
|
self._write_to_screen(msg2, stderr)
|