Merge pull request #41856 from meaksh/2017.7-suse-leftovers-part-two

SUSE leftovers for 2017.7.0 RC
This commit is contained in:
Mike Place 2017-06-21 10:24:37 -05:00 committed by GitHub
commit 278b5614d0
18 changed files with 1621 additions and 14 deletions

1230
conf/suse/master Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
[Unit]
Description=The Salt API
Documentation=man:salt-api(1) file:///usr/share/doc/salt/html/contents.html https://docs.saltstack.com/en/latest/contents.html
After=network.target
[Service]
User=salt
Type=simple
Environment=SHELL=/bin/bash
LimitNOFILE=8192
ExecStart=/usr/bin/salt-api
TimeoutStopSec=3

View File

@ -0,0 +1,25 @@
/var/log/salt/master {
su salt salt
weekly
missingok
rotate 7
compress
notifempty
}
/var/log/salt/minion {
weekly
missingok
rotate 7
compress
notifempty
}
/var/log/salt/key {
su salt salt
weekly
missingok
rotate 7
compress
notifempty
}

View File

@ -0,0 +1,13 @@
[Unit]
Description=The Salt Master Server
Documentation=man:salt-master(1) file:///usr/share/doc/salt/html/contents.html https://docs.saltstack.com/en/latest/contents.html
After=network.target
[Service]
LimitNOFILE=16384
Type=simple
ExecStart=/usr/bin/salt-master
TasksMax=infinity
[Install]
WantedBy=multi-user.target

23
pkg/suse/salt-minion Normal file → Executable file
View File

@ -51,8 +51,23 @@ SERVICE=salt-minion
PROCESS=salt-minion
RETVAL=0
WATCHDOG_CRON="/etc/cron.d/salt-minion"
set_watchdog() {
if [ ! -f $WATCHDOG_CRON ]; then
echo -e '* * * * * root /usr/bin/salt-daemon-watcher --with-init\n' > $WATCHDOG_CRON
# Kick the watcher for 1 minute immediately, because cron will wake up only afterwards
/usr/bin/salt-daemon-watcher --with-init & disown
fi
}
remove_watchdog() {
rm $WATCHDOG_CRON 2>/dev/null || true
kill -9 $(ps uax | grep [s]alt-daemon-watcher | awk '{print $2}') 2>/dev/null
}
start() {
set_watchdog;
echo -n $"Starting salt-minion daemon: "
if [ -f $SUSE_RELEASE ]; then
startproc -p /var/run/$SERVICE.pid $SALTMINION -d $MINION_ARGS
@ -80,6 +95,10 @@ start() {
}
stop() {
IS_RESTARTING=$1
if [ -z $IS_RESTARTING ]; then
remove_watchdog;
fi
echo -n $"Stopping salt-minion daemon: "
if [ -f $SUSE_RELEASE ]; then
killproc -TERM $SALTMINION
@ -101,8 +120,8 @@ stop() {
}
restart() {
stop
start
stop 1;
start;
}
# See how we were called.

View File

@ -0,0 +1,14 @@
[Unit]
Description=The Salt Minion
After=network.target
[Service]
Type=simple
LimitNOFILE=8192
ExecStart=/usr/bin/salt-minion
KillMode=process
Restart=on-failure
RestartSec=15
[Install]
WantedBy=multi-user.target

View File

@ -427,16 +427,30 @@ def _run(name, **kwargs):
ret['result'] = False
return ret
if aspec.varargs and aspec.varargs in kwargs:
varargs = kwargs.pop(aspec.varargs)
if aspec.varargs:
if aspec.varargs == 'name':
rarg = 'm_name'
elif aspec.varargs == 'fun':
rarg = 'm_fun'
elif aspec.varargs == 'names':
rarg = 'm_names'
elif aspec.varargs == 'state':
rarg = 'm_state'
elif aspec.varargs == 'saltenv':
rarg = 'm_saltenv'
else:
rarg = aspec.varargs
if not isinstance(varargs, list):
msg = "'{0}' must be a list."
ret['comment'] = msg.format(aspec.varargs)
ret['result'] = False
return ret
if rarg in kwargs:
varargs = kwargs.pop(rarg)
args.extend(varargs)
if not isinstance(varargs, list):
msg = "'{0}' must be a list."
ret['comment'] = msg.format(aspec.varargs)
ret['result'] = False
return ret
args.extend(varargs)
nkwargs = {}
if aspec.keywords and aspec.keywords in kwargs:

View File

@ -1877,7 +1877,7 @@ def downloaded(name,
ignore_epoch=None,
**kwargs):
'''
.. versionadded:: Oxygen
.. versionadded:: 2017.7.0
Ensure that the package is downloaded, and that it is the correct version
(if specified).
@ -2014,7 +2014,7 @@ def downloaded(name,
def patch_installed(name, advisory_ids=None, downloadonly=None, **kwargs):
'''
.. versionadded:: Oxygen
.. versionadded:: 2017.7.0
Ensure that packages related to certain advisory ids are installed.
@ -2094,7 +2094,7 @@ def patch_installed(name, advisory_ids=None, downloadonly=None, **kwargs):
def patch_downloaded(name, advisory_ids=None, **kwargs):
'''
.. versionadded:: Oxygen
.. versionadded:: 2017.7.0
Ensure that packages related to certain advisory ids are downloaded.

View File

@ -0,0 +1,26 @@
#!/bin/bash
#
# Author: Bo Maryniuk <bo@suse.de>
# Requires: yum install propcps
#
# Runs every minute from crontab,
# checks salt-minion every 10 seconds.
#
# Use this with a following crontab:
# * * * * * /path/to/this/script
if [ "$1" != "--with-init" ]; then
echo "This command is not used directly."
exit 1;
fi
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
for iter in {1..5}; do
if [[ $(pgrep salt-minion) == "" ]]; then
service salt-minion restart
fi
sleep 10;
done
true

View File

@ -0,0 +1,20 @@
## What it is
Plugin which provides a notification mechanism to Salt, if Yum is
used outside of it.
## Installation
Configuration files are going to:
`/etc/yum/pluginconf.d/[name].conf`
Plugin itself goes to:
`/usr/share/yum-plugins/[name].conf`
## Permissions
User: root
Group: root
Mode: 644

View File

@ -0,0 +1,2 @@
[main]
enabled=1

View File

@ -0,0 +1,55 @@
# Copyright (c) 2016 SUSE Linux LLC
# All Rights Reserved.
#
# Author: Bo Maryniuk <bo@suse.de>
from yum.plugins import TYPE_CORE
from yum import config
import os
import hashlib
CK_PATH = "/var/cache/salt/minion/rpmdb.cookie"
RPM_PATH = "/var/lib/rpm/Packages"
requires_api_version = '2.5'
plugin_type = TYPE_CORE
def _get_mtime():
"""
Get the modified time of the RPM Database.
Returns:
Unix ticks
"""
return os.path.exists(RPM_PATH) and int(os.path.getmtime(RPM_PATH)) or 0
def _get_checksum():
"""
Get the checksum of the RPM Database.
Returns:
hexdigest
"""
digest = hashlib.md5()
with open(RPM_PATH, "rb") as rpm_db_fh:
while True:
buff = rpm_db_fh.read(0x1000)
if not buff:
break
digest.update(buff)
return digest.hexdigest()
def posttrans_hook(conduit):
"""
Hook after the package installation transaction.
:param conduit:
:return:
"""
# Integrate Yum with Salt
if 'SALT_RUNNING' not in os.environ:
with open(CK_PATH, 'w') as ck_fh:
ck_fh.write('{chksum} {mtime}\n'.format(chksum=_get_checksum(), mtime=_get_mtime()))

View File

@ -0,0 +1,3 @@
# Zypper plugins
Plugins here are required to interact with SUSE Manager in conjunction of SaltStack and Zypper.

View File

@ -0,0 +1,59 @@
#!/usr/bin/python
#
# Copyright (c) 2016 SUSE Linux LLC
# All Rights Reserved.
#
# Author: Bo Maryniuk <bo@suse.de>
import sys
import os
import hashlib
from zypp_plugin import Plugin
class DriftDetector(Plugin):
"""
Return diff of the installed packages outside the Salt.
"""
def __init__(self):
Plugin.__init__(self)
self.ck_path = "/var/cache/salt/minion/rpmdb.cookie"
self.rpm_path = "/var/lib/rpm/Packages"
def _get_mtime(self):
'''
Get the modified time of the RPM Database.
Returns:
Unix ticks
'''
return os.path.exists(self.rpm_path) and int(os.path.getmtime(self.rpm_path)) or 0
def _get_checksum(self):
'''
Get the checksum of the RPM Database.
Returns:
hexdigest
'''
digest = hashlib.md5()
with open(self.rpm_path, "rb") as rpm_db_fh:
while True:
buff = rpm_db_fh.read(0x1000)
if not buff:
break
digest.update(buff)
return digest.hexdigest()
def PLUGINEND(self, headers, body):
"""
Hook when plugin closes Zypper's transaction.
"""
if 'SALT_RUNNING' not in os.environ:
with open(self.ck_path, 'w') as ck_fh:
ck_fh.write('{chksum} {mtime}\n'.format(chksum=self._get_checksum(), mtime=self._get_mtime()))
self.ack()
DriftDetector().main()

View File

@ -73,9 +73,15 @@ class ModuleStateTest(TestCase, LoaderModuleMockMixin):
keywords=None,
defaults=False)
cls.bspec = ArgSpec(args=[],
varargs='names',
keywords='kwargs',
defaults=None)
@classmethod
def tearDownClass(cls):
del cls.aspec
del cls.bspec
def test_run_module_not_available(self):
'''
@ -88,6 +94,16 @@ class ModuleStateTest(TestCase, LoaderModuleMockMixin):
assert ret['comment'] == "Unavailable function: {0}.".format(CMD)
assert not ret['result']
def test_module_run_hidden_varargs(self):
'''
Tests the return of module.run state when hidden varargs are used with
wrong type.
'''
with patch('salt.utils.args.get_function_argspec', MagicMock(return_value=self.bspec)):
ret = module._run(CMD, m_names='anyname')
comment = "'names' must be a list."
self.assertEqual(ret['comment'], comment)
def test_run_testmode(self):
'''
Tests the return of the module.run state when test=True is passed.

View File

@ -37,6 +37,7 @@ EXCLUDED_FILES = [
'tests/consist.py',
'tests/modparser.py',
'tests/committer_parser.py',
'tests/zypp_plugin.py',
'tests/unit/transport/mixins.py',
'tests/integration/utils/testprogram.py',
]

View File

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Bo Maryniuk <bo@suse.de>`
'''
# Import Python Libs
from __future__ import absolute_import
# Import Salt Testing Libs
from tests.support.unit import TestCase, skipIf
from tests.support.mock import (
MagicMock,
patch,
NO_MOCK,
NO_MOCK_REASON
)
import os
import imp
from zypp_plugin import BogusIO
zyppnotify = imp.load_source('zyppnotify', os.path.sep.join(os.path.dirname(__file__).split(
os.path.sep)[:-2] + ['scripts', 'suse', 'zypper', 'plugins', 'commit', 'zyppnotify']))
@skipIf(NO_MOCK, NO_MOCK_REASON)
class ZyppPluginsTestCase(TestCase):
'''
Test shipped libzypp plugins.
'''
def test_drift_detector(self):
'''
Test drift detector for a correct cookie file.
Returns:
'''
drift = zyppnotify.DriftDetector()
drift._get_mtime = MagicMock(return_value=123)
drift._get_checksum = MagicMock(return_value='deadbeef')
bogus_io = BogusIO()
with patch('__builtin__.open', bogus_io):
drift.PLUGINEND(None, None)
self.assertEqual(str(bogus_io), 'deadbeef 123\n')
self.assertEqual(bogus_io.mode, 'w')
self.assertEqual(bogus_io.path, '/var/cache/salt/minion/rpmdb.cookie')

65
tests/zypp_plugin.py Normal file
View File

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
'''
Related to zypp_plugins_test.py module.
'''
class Plugin(object):
'''
Bogus module for Zypp Plugins tests.
'''
def ack(self):
'''
Acknowledge that the plugin had finished the transaction
Returns:
'''
def main(self):
'''
Register plugin
Returns:
'''
class BogusIO(object):
'''
Read/write logger.
'''
def __init__(self):
self.content = list()
self.closed = False
def __str__(self):
return '\n'.join(self.content)
def __call__(self, *args, **kwargs):
self.path, self.mode = args
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def __enter__(self):
return self
def write(self, data):
'''
Simulate writing data
Args:
data:
Returns:
'''
self.content.append(data)
def close(self):
'''
Simulate closing the IO object.
Returns:
'''
self.closed = True