11
11
from landscape.lib.twisted_util import gather_results
12
12
from landscape.lib.fetch import fetch_async
14
from landscape.package.taskhandler import PackageTaskHandler, run_task_handler
14
from landscape.package.taskhandler import (
15
PackageTaskHandlerConfiguration, PackageTaskHandler, run_task_handler)
15
16
from landscape.package.store import UnknownHashIDRequest
19
20
MAX_UNKNOWN_HASHES_PER_REQUEST = 500
23
class PackageReporterConfiguration(PackageTaskHandlerConfiguration):
24
"""Specialized configuration for the Landscape package-reporter."""
26
def make_parser(self):
28
Specialize L{Configuration.make_parser}, adding options
29
reporter-specific options.
31
parser = super(PackageReporterConfiguration, self).make_parser()
32
parser.add_option("--force-smart-update", default=False,
34
help="Force running smart-update.")
22
38
class PackageReporter(PackageTaskHandler):
23
39
"""Report information about the system packages.
26
42
@cvar smart_update_interval: Time interval in minutes to pass to
27
43
the C{--after} command line option of C{smart-update}.
45
config_factory = PackageReporterConfiguration
29
47
queue_name = "reporter"
30
49
smart_update_interval = 60
31
50
smart_update_filename = "/usr/lib/landscape/smart-update"
102
122
logging.warning("Couldn't download hash=>id database: %s" %
105
result = fetch_async(url)
125
result = fetch_async(url,
126
cainfo=self._config.get("ssl_public_key"))
106
127
result.addCallback(fetch_ok)
107
128
result.addErrback(fetch_error)
135
156
@return: a deferred returning (out, err, code)
158
if self._config.force_smart_update:
161
args = ("--after", "%d" % self.smart_update_interval)
137
162
result = getProcessOutputAndValue(self.smart_update_filename,
138
args=("--after", "%d" %
139
self.smart_update_interval))
141
165
def callback((out, err, code)):
142
166
# smart-update --after N will exit with error code 1 when it
215
238
# This problem would happen for example when switching the client from
216
239
# one Landscape server to another, because the uuid-changed event would
217
240
# cause a resynchronize task to be created by the monitor. See #417122.
219
#self._store.clear_hash_id_requests()
221
242
return succeed(None)
327
348
request = self._store.add_hash_id_request(unknown_hashes)
328
349
message["request-id"] = request.id
329
350
result = self._broker.send_message(message, True)
330
352
def set_message_id(message_id):
331
353
request.message_id = message_id
332
355
def send_message_failed(failure):
335
359
return result.addCallbacks(set_message_id, send_message_failed)
337
361
def detect_changes(self):
342
366
- are now installed, and were not;
343
367
- are now available, and were not;
368
- are now locked, and were not;
344
369
- were previously available but are not anymore;
345
370
- were previously installed but are not anymore;
371
- were previously locked but are not anymore;
373
Additionally it will report package locks that:
375
- are now set, and were not;
376
- were previously set but are not anymore;
347
378
In all cases, the server is notified of the new situation
348
379
with a "packages" message.
352
383
old_installed = set(self._store.get_installed())
353
384
old_available = set(self._store.get_available())
354
385
old_upgrades = set(self._store.get_available_upgrades())
386
old_locked = set(self._store.get_locked())
356
388
current_installed = set()
357
389
current_available = set()
358
390
current_upgrades = set()
391
current_locked = set()
360
393
for package in self._facade.get_packages():
361
394
hash = self._facade.get_package_hash(package)
422
for package in self._facade.get_locked_packages():
423
hash = self._facade.get_package_hash(package)
424
id = self._store.get_hash_id(hash)
426
current_locked.add(id)
389
428
new_installed = current_installed - old_installed
390
429
new_available = current_available - old_available
391
430
new_upgrades = current_upgrades - old_upgrades
431
new_locked = current_locked - old_locked
393
433
not_installed = old_installed - current_installed
394
434
not_available = old_available - current_available
395
435
not_upgrades = old_upgrades - current_upgrades
436
not_locked = old_locked - current_locked
398
439
if new_installed:
425
472
logging.info("Queuing message with changes in known packages: "
426
473
"%d installed, %d available, %d available upgrades, "
427
"%d not installed, %d not available, %d not "
428
"available upgrades."
474
"%d locked, %d not installed, %d not available, "
475
"%d not available upgrades, %d not locked."
429
476
% (len(new_installed), len(new_available),
430
len(new_upgrades), len(not_installed),
431
len(not_available), len(not_upgrades)))
477
len(new_upgrades), len(new_locked),
478
len(not_installed), len(not_available),
479
len(not_upgrades), len(not_locked)))
433
481
def update_currently_known(result):
434
482
if new_installed:
437
485
self._store.remove_installed(not_installed)
438
486
if new_available:
439
487
self._store.add_available(new_available)
489
self._store.add_locked(new_locked)
440
490
if not_available:
441
491
self._store.remove_available(not_available)
443
493
self._store.add_available_upgrades(new_upgrades)
445
495
self._store.remove_available_upgrades(not_upgrades)
497
self._store.remove_locked(not_locked)
499
result.addCallback(update_currently_known)
503
def detect_package_locks_changes(self):
504
"""Detect changes in known package locks.
506
This method will verify if there are package locks that:
508
- are now set, and were not;
509
- were previously set but are not anymore;
511
In all cases, the server is notified of the new situation
512
with a "packages" message.
514
old_package_locks = set(self._store.get_package_locks())
515
current_package_locks = set(self._facade.get_package_locks())
517
set_package_locks = current_package_locks - old_package_locks
518
unset_package_locks = old_package_locks - current_package_locks
521
if set_package_locks:
522
message["created"] = sorted(set_package_locks)
523
if unset_package_locks:
524
message["deleted"] = sorted(unset_package_locks)
527
result = succeed(None)
529
message["type"] = "package-locks"
531
result = self._broker.send_message(message, True)
533
logging.info("Queuing message with changes in known package locks:"
534
" %d created, %d deleted." %
535
(len(set_package_locks), len(unset_package_locks)))
537
def update_currently_known(result):
538
if set_package_locks:
539
self._store.add_package_locks(set_package_locks)
540
if unset_package_locks:
541
self._store.remove_package_locks(unset_package_locks)
447
543
result.addCallback(update_currently_known)