Skip to content

Commit

Permalink
Add log collection tool and thread (#1987)
Browse files Browse the repository at this point in the history
  • Loading branch information
pgombar authored Sep 10, 2020
1 parent 9a25e21 commit e79c9da
Show file tree
Hide file tree
Showing 27 changed files with 818 additions and 221 deletions.
88 changes: 58 additions & 30 deletions azurelinuxagent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@
from __future__ import print_function

import os
import sys
import re
import subprocess
import sys
import threading
import traceback

import azurelinuxagent.common.logger as logger
import azurelinuxagent.common.event as event
import azurelinuxagent.common.conf as conf
from azurelinuxagent.common.version import AGENT_NAME, AGENT_LONG_VERSION, \
DISTRO_NAME, DISTRO_VERSION, \
PY_VERSION_MAJOR, PY_VERSION_MINOR, \
PY_VERSION_MICRO, GOAL_STATE_AGENT_VERSION
import azurelinuxagent.common.event as event
import azurelinuxagent.common.logger as logger
from azurelinuxagent.common.future import ustr
from azurelinuxagent.common.logcollector import LogCollector, OUTPUT_RESULTS_FILE_PATH
from azurelinuxagent.common.osutil import get_osutil
from azurelinuxagent.common.utils import fileutil
from azurelinuxagent.common.version import AGENT_NAME, AGENT_LONG_VERSION, \
DISTRO_NAME, DISTRO_VERSION, \
PY_VERSION_MAJOR, PY_VERSION_MINOR, \
PY_VERSION_MICRO, GOAL_STATE_AGENT_VERSION


class Agent(object):
Expand All @@ -49,17 +51,17 @@ def __init__(self, verbose, conf_file_path=None):
self.conf_file_path = conf_file_path
self.osutil = get_osutil()

#Init stdout log
# Init stdout log
level = logger.LogLevel.VERBOSE if verbose else logger.LogLevel.INFO
logger.add_logger_appender(logger.AppenderType.STDOUT, level)

#Init config
# Init config
conf_file_path = self.conf_file_path \
if self.conf_file_path is not None \
else self.osutil.get_agent_conf_file_path()
conf.load_conf_from_file(conf_file_path)

#Init log
# Init log
verbose = verbose or conf.get_logs_verbose()
level = logger.LogLevel.VERBOSE if verbose else logger.LogLevel.INFO
logger.add_logger_appender(logger.AppenderType.FILE, level,
Expand Down Expand Up @@ -104,7 +106,6 @@ def daemon(self):
child_args = None \
if self.conf_file_path is None \
else "-configuration-path:{0}".format(self.conf_file_path)

from azurelinuxagent.daemon import get_daemon_handler
daemon_handler = get_daemon_handler()
daemon_handler.run(child_args=child_args)
Expand Down Expand Up @@ -151,6 +152,22 @@ def show_configuration(self):
for k in sorted(configuration.keys()):
print("{0} = {1}".format(k, configuration[k]))

def collect_logs(self, is_full_mode):
if is_full_mode:
print("Running log collector mode full")
else:
print("Running log collector mode normal")

try:
log_collector = LogCollector(is_full_mode)
archive = log_collector.collect_logs_and_get_archive()
print("Log collection successfully completed. Archive can be found at {0} "
"and detailed log output can be found at {1}".format(archive, OUTPUT_RESULTS_FILE_PATH))
except Exception as e: # pylint: disable=C0103
print("Log collection completed unsuccessfully. Error: {0}".format(ustr(e)))
print("Detailed log output can be found at {0}".format(OUTPUT_RESULTS_FILE_PATH))
sys.exit(1)


def main(args=[]): # pylint: disable=R0912,W0102
"""
Expand All @@ -159,7 +176,7 @@ def main(args=[]): # pylint: disable=R0912,W0102
"""
if len(args) <= 0: # pylint: disable=len-as-condition
args = sys.argv[1:]
command, force, verbose, debug, conf_file_path = parse_args(args)
command, force, verbose, debug, conf_file_path, log_collector_full_mode = parse_args(args)
if command == "version":
version()
elif command == "help":
Expand All @@ -183,11 +200,14 @@ def main(args=[]): # pylint: disable=R0912,W0102
agent.run_exthandlers(debug)
elif command == "show-configuration":
agent.show_configuration()
elif command == "collect-logs":
agent.collect_logs(log_collector_full_mode)
except Exception:
logger.error(u"Failed to run '{0}': {1}",
command,
traceback.format_exc())


def parse_args(sys_args): # pylint: disable=R0912
"""
Parse command line arguments
Expand All @@ -197,45 +217,50 @@ def parse_args(sys_args): # pylint: disable=R0912
verbose = False
debug = False
conf_file_path = None
for a in sys_args: # pylint: disable=C0103
m = re.match("^(?:[-/]*)configuration-path:([\w/\.\-_]+)", a) # pylint: disable=W1401,C0103
log_collector_full_mode = False

for arg in sys_args:
m = re.match("^(?:[-/]*)configuration-path:([\w/\.\-_]+)", arg) # pylint: disable=W1401,C0103
if not m is None:
conf_file_path = m.group(1)
if not os.path.exists(conf_file_path):
print("Error: Configuration file {0} does not exist".format(
conf_file_path), file=sys.stderr)
usage()
print(usage())
sys.exit(1)

elif re.match("^([-/]*)deprovision\\+user", a):
elif re.match("^([-/]*)deprovision\\+user", arg):
cmd = "deprovision+user"
elif re.match("^([-/]*)deprovision", a):
elif re.match("^([-/]*)deprovision", arg):
cmd = "deprovision"
elif re.match("^([-/]*)daemon", a):
elif re.match("^([-/]*)daemon", arg):
cmd = "daemon"
elif re.match("^([-/]*)start", a):
elif re.match("^([-/]*)start", arg):
cmd = "start"
elif re.match("^([-/]*)register-service", a):
elif re.match("^([-/]*)register-service", arg):
cmd = "register-service"
elif re.match("^([-/]*)run-exthandlers", a):
elif re.match("^([-/]*)run-exthandlers", arg):
cmd = "run-exthandlers"
elif re.match("^([-/]*)version", a):
elif re.match("^([-/]*)version", arg):
cmd = "version"
elif re.match("^([-/]*)verbose", a):
elif re.match("^([-/]*)verbose", arg):
verbose = True
elif re.match("^([-/]*)debug", a):
elif re.match("^([-/]*)debug", arg):
debug = True
elif re.match("^([-/]*)force", a):
elif re.match("^([-/]*)force", arg):
force = True
elif re.match("^([-/]*)show-configuration", a):
elif re.match("^([-/]*)show-configuration", arg):
cmd = "show-configuration"
elif re.match("^([-/]*)(help|usage|\\?)", a):
elif re.match("^([-/]*)(help|usage|\\?)", arg):
cmd = "help"
elif re.match("^([-/]*)collect-logs", arg):
cmd = "collect-logs"
elif re.match("^([-/]*)full", arg):
log_collector_full_mode = True
else:
cmd = "help"
break

return cmd, force, verbose, debug, conf_file_path
return cmd, force, verbose, debug, conf_file_path, log_collector_full_mode


def version():
Expand All @@ -250,6 +275,7 @@ def version():
PY_VERSION_MICRO))
print("Goal state agent: {0}".format(GOAL_STATE_AGENT_VERSION))


def usage():
"""
Return agent usage message
Expand All @@ -258,11 +284,12 @@ def usage():
s += ("usage: {0} [-verbose] [-force] [-help] " # pylint: disable=C0103
"-configuration-path:<path to configuration file>"
"-deprovision[+user]|-register-service|-version|-daemon|-start|"
"-run-exthandlers|-show-configuration]"
"-run-exthandlers|-show-configuration|-collect-logs [-full]"
"").format(sys.argv[0])
s += "\n" # pylint: disable=C0103
return s


def start(conf_file_path=None):
"""
Start agent daemon in a background process and set stdout/stderr to
Expand All @@ -274,5 +301,6 @@ def start(conf_file_path=None):
args.append('-configuration-path:{0}'.format(conf_file_path))
subprocess.Popen(args, stdout=devnull, stderr=devnull)


if __name__ == '__main__' :
main()
7 changes: 4 additions & 3 deletions azurelinuxagent/common/cgroupapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
VM_AGENT_CGROUP_NAME = "walinuxagent.service"
EXTENSIONS_ROOT_CGROUP_NAME = "walinuxagent.extensions"
UNIT_FILES_FILE_SYSTEM_PATH = "/etc/systemd/system"
SYSTEMD_RUN_PATH = "/run/systemd/system/"


class CGroupsApi(object):
Expand Down Expand Up @@ -94,15 +95,15 @@ def create():
"""
Factory method to create the correct API for the current platform
"""
return SystemdCgroupsApi() if CGroupsApi._is_systemd() else FileSystemCgroupsApi()
return SystemdCgroupsApi() if CGroupsApi.is_systemd() else FileSystemCgroupsApi()

@staticmethod
def _is_systemd():
def is_systemd():
"""
Determine if systemd is managing system services; the implementation follows the same strategy as, for example,
sd_booted() in libsystemd, or /usr/sbin/service
"""
return os.path.exists('/run/systemd/system/')
return os.path.exists(SYSTEMD_RUN_PATH)

@staticmethod
def _foreach_controller(operation, message):
Expand Down
18 changes: 16 additions & 2 deletions azurelinuxagent/common/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def load_conf_from_file(conf_file_path, conf=__conf__):
"OS.CheckRdmaDriver": False,
"Logs.Verbose": False,
"Logs.Console": True,
"Logs.Collect": False,
"Extensions.Enabled": True,
"Provisioning.AllowResetSysUser": False,
"Provisioning.RegenerateSshHostKeyPair": False,
Expand Down Expand Up @@ -149,7 +150,8 @@ def load_conf_from_file(conf_file_path, conf=__conf__):
"Provisioning.PasswordCryptSaltLength": 10,
"HttpProxy.Port": None,
"ResourceDisk.SwapSizeMB": 0,
"Autoupdate.Frequency": 3600
"Autoupdate.Frequency": 3600,
"Logs.CollectPeriod": 3600
}


Expand Down Expand Up @@ -223,6 +225,14 @@ def get_logs_console(conf=__conf__):
return conf.get_switch("Logs.Console", True)


def get_collect_logs(conf=__conf__):
return conf.get_switch("Logs.Collect", False)


def get_collect_logs_period(conf=__conf__):
return conf.get_int("Logs.CollectPeriod", 3600)


def get_lib_dir(conf=__conf__):
return conf.get("Lib.Dir", "/var/lib/waagent")

Expand Down Expand Up @@ -374,9 +384,11 @@ def get_password_crypt_salt_len(conf=__conf__):
def get_monitor_hostname(conf=__conf__):
return conf.get_switch("Provisioning.MonitorHostName", False)


def get_monitor_hostname_period(conf=__conf__):
return conf.get_int("Provisioning.MonitorHostNamePeriod", 30)


def get_httpproxy_host(conf=__conf__):
return conf.get("HttpProxy.Host", None)

Expand All @@ -395,10 +407,12 @@ def get_resourcedisk_format(conf=__conf__):

def get_resourcedisk_enable_swap(conf=__conf__):
return conf.get_switch("ResourceDisk.EnableSwap", False)



def get_resourcedisk_enable_swap_encryption(conf=__conf__):
return conf.get_switch("ResourceDisk.EnableSwapEncryption", False)


def get_resourcedisk_mountpoint(conf=__conf__):
return conf.get("ResourceDisk.MountPoint", "/mnt/resource")

Expand Down
1 change: 1 addition & 0 deletions azurelinuxagent/common/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class WALAEventOperation: # pylint: disable=R0903,no-init
InitializeHostPlugin = "InitializeHostPlugin"
InvokeCommandUsingSystemd = "InvokeCommandUsingSystemd"
Log = "Log"
LogCollection = "LogCollection"
OSInfo = "OSInfo"
Partition = "Partition"
PluginSettingsVersionMismatch = "PluginSettingsVersionMismatch"
Expand Down
Loading

0 comments on commit e79c9da

Please sign in to comment.