Skip to content

Commit

Permalink
Merge pull request #4505 from zenoss/release/7.2.1
Browse files Browse the repository at this point in the history
ZEN-34886: CZ 7.2.1 : Garfield Extended Fixes
  • Loading branch information
Deer-WarLord authored Jul 29, 2024
2 parents 1a07d7b + eb8979e commit a90ebb2
Show file tree
Hide file tree
Showing 79 changed files with 3,553 additions and 955 deletions.
32 changes: 21 additions & 11 deletions Products/DataCollector/zenmodeler.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
from Products.ZenEvents.ZenEventClasses import Heartbeat, Error
from Products.ZenHub.PBDaemon import FakeRemote, PBDaemon, HubDown
from Products.ZenUtils.Driver import drive, driveLater
from Products.ZenUtils.Utils import unused, zenPath
from Products.ZenUtils.Utils import unused, zenPath, wait
from Products.Zuul.utils import safe_hasattr as hasattr

# needed for Twisted's PB (Perspective Broker) to work
Expand Down Expand Up @@ -889,17 +889,23 @@ def heartbeat(self, ignored=None):
# We start modeling from here to accomodate the startup delay.

if not self.started:
if self.immediate == 0 and self.startat:
# This stuff relies on ARBITRARY_BEAT being < 60s
if self.timeMatches():
self.started = True
self.log.info("Starting modeling...")
reactor.callLater(1, self.main)
if self.immediate == 0:
if self.startat:
# This stuff relies on ARBITRARY_BEAT being < 60s
if self.timeMatches():
# Run modeling in case we have now=False, startat is not None and local time matches the startat
self.started = True
self.log.info("Starting modeling...")
reactor.callLater(1, self.main)
elif not self.isMainScheduled:
# Or run modeling by cycleTime in case we have now=False, startat is None
# and we haven't set schedule by cycleTime yet
self.isMainScheduled = True
reactor.callLater(self.cycleTime(), self.main)
else:
self.started = True
# Going back to the normal modeling schedule either cron or cycleTime
# after the first immediate modeling during service startup
self.immediate = 0
self.log.info(
"Starting modeling in %s seconds.", self.startDelay
)
Expand Down Expand Up @@ -941,6 +947,7 @@ def _devicegen_has_items(self):
self.devicegen = chain([first], self.devicegen)
return result

@defer.inlineCallbacks
def checkStop(self, unused=None):
"""
Check to see if there's anything to do.
Expand Down Expand Up @@ -980,6 +987,11 @@ def checkStop(self, unused=None):
if not self.options.cycle:
self.stop()
self.finished = []
# frequency of heartbeat rate could be 2 times per minute in case we have
# cron job modeling faster than 1 minute it'll be trigger a second time
if runTime < 60 and self.startat is not None:
yield wait(60)
self.started = False

def fillCollectionSlots(self, driver):
"""
Expand Down Expand Up @@ -1040,8 +1052,6 @@ def timeMatches(self):
Check whether the current time matches a cron-like
specification, return a straight true or false
"""
if self.startat is None:
return True

def match_entity(entity, value):
if entity == "*":
Expand Down Expand Up @@ -1333,7 +1343,7 @@ def mainLoop(self, driver):
@return: Twisted deferred object
@rtype: Twisted deferred object
"""
if self.options.cycle:
if self.options.cycle and self.startat is None:
self.isMainScheduled = True
driveLater(self.cycleTime(), self.mainLoop)

Expand Down
54 changes: 52 additions & 2 deletions Products/Jobber/bin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#
##############################################################################


def main():
import sys

Expand All @@ -16,6 +15,9 @@ def main():
from celery.bin.celery import main
from Products.ZenUtils.Utils import load_config

# work-around for celery's `--help` bug.
_print_help_when_requested()

# Dynamic configuration shenanigans because Celery can't be re-configured
# after its initial configuration has been set.
_configure_celery()
Expand All @@ -28,11 +30,59 @@ def main():
sys.exit(main())


# Note: an empty tuple implies repetition of the key
_import_names = {
"inspect": ("control", "inspect"),
"list": ("list", "list_"),
"report": ("celery", "report"),
"help": ("celery", "help"),
}


def _get_command(modname, cmdname):
import importlib

module = importlib.import_module("celery.bin.{}".format(modname))
return getattr(module, cmdname)


def _print_help_when_requested():
import sys
from Products.Jobber.zenjobs import app

if "--help" not in sys.argv:
return

name = sys.argv[1]

if name == "--help":
sys.argv[1:] = ["help"]
return

if name == "monitor":
from Products.Jobber.monitor.command import MonitorCommand

w = MonitorCommand(app=app)
p = w.create_parser("zenjobs", "monitor")
else:
modname, cmdname = _import_names.get(sys.argv[1], (name, name))
command = _get_command(modname, cmdname)
cmd = command(app=app)
p = cmd.create_parser(sys.argv[0], name)

p.print_help()
sys.exit(0)


def _configure_celery():
import argparse
import sys
from Products.Jobber import config

# If '--help' was passed as an argument, don't attempt configuration.
if "--help" in sys.argv:
return

parser = argparse.ArgumentParser()
parser.add_argument("--config-file")

Expand All @@ -41,5 +91,5 @@ def _configure_celery():
return

cfg = config.getConfig(args.config_file)
config.ZenCeleryConfig = config.CeleryConfig.from_config(cfg)
config.ZenCeleryConfig = config.from_config(cfg)
sys.argv[1:] = remainder
43 changes: 22 additions & 21 deletions Products/Jobber/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,27 +142,28 @@ class CeleryConfig(object):
CELERYBEAT_REDIRECT_STDOUTS = attr.ib(default=True)
CELERYBEAT_REDIRECT_STDOUTS_LEVEL = attr.ib(default="INFO")

@classmethod
def from_config(cls, cfg={}):
args = {
"broker_url": buildBrokerUrl(cfg),
"result_backend": cfg.get("redis-url"),
"result_expires": cfg.get("zenjobs-job-expires"),
"worker_concurrency": cfg.get("concurrent-jobs"),
"worker_max_tasks_per_child": cfg.get("max-jobs-per-worker"),
"task_time_limit": cfg.get("job-hard-time-limit"),
"task_soft_time_limit": cfg.get("job-soft-time-limit"),
"beat_max_loop_interval": cfg.get(
"scheduler-max-loop-interval"
),
"worker_proc_alive_timeout": cfg.get("zenjobs-worker-alive-timeout"),
}
tz = os.environ.get("TZ")
if tz:
args["timezone"] = tz

return cls(**args)

def from_config(cfg=None):
cfg = cfg if cfg is not None else {}
args = {
"broker_url": buildBrokerUrl(cfg),
"result_backend": cfg.get("redis-url"),
"result_expires": cfg.get("zenjobs-job-expires"),
"worker_concurrency": cfg.get("concurrent-jobs"),
"worker_max_tasks_per_child": cfg.get("max-jobs-per-worker"),
"task_time_limit": cfg.get("job-hard-time-limit"),
"task_soft_time_limit": cfg.get("job-soft-time-limit"),
"beat_max_loop_interval": cfg.get(
"scheduler-max-loop-interval"
),
"worker_proc_alive_timeout": cfg.get("zenjobs-worker-alive-timeout"),
}
tz = os.environ.get("TZ")
if tz:
args["timezone"] = tz

return CeleryConfig(**args)


# Initialized with default values (for when --config-file is not specified)
ZenCeleryConfig = CeleryConfig.from_config(getConfig())
ZenCeleryConfig = from_config(getConfig())
2 changes: 1 addition & 1 deletion Products/Jobber/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ def run(self):


def _get_hash(config):
return hashlib.md5(
return hashlib.sha256(
"".join("{0}{1}".format(k, config[k]) for k in sorted(config))
).hexdigest()

Expand Down
137 changes: 0 additions & 137 deletions Products/Jobber/monitor.py

This file was deleted.

12 changes: 12 additions & 0 deletions Products/Jobber/monitor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
##############################################################################
#
# Copyright (C) Zenoss, Inc. 2024, all rights reserved.
#
# This content is made available according to terms specified in
# License.zenoss under the directory where your Zenoss product is installed.
#
##############################################################################

from .command import MonitorCommand

__all__ = ("MonitorCommand",)
Loading

0 comments on commit a90ebb2

Please sign in to comment.