Page MenuHomeVyOS Platform

syslog.py
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

syslog.py

#!/usr/bin/env python3
#
# Copyright (C) 2018 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
import sys
import os
import re
import jinja2
from vyos.config import Config
from vyos import ConfigError
########### config templates
#### /etc/rsyslog.d/vyos-rsyslog.conf ###
configs = '''
## generated by syslog.py ##
## file based logging
{% for file in files %}
$outchannel {{file}},{{files[file]['log-file']}},{{files[file]['max-size']}},{{files[file]['action-on-max-size']}}
{{files[file]['selectors']}} :omfile:${{file}}
{% endfor %}
{% if console %}
## console logging
{% for con in console %}
{{console[con]['selectors']}} /dev/console
{% endfor %}
{% endif %}
{% if hosts %}
## remote logging
{% for host in hosts %}
{% if hosts[host]['proto'] == 'tcp' %}
{{hosts[host]['selectors']}} @@{{host}}
{% else %}
{{hosts[host]['selectors']}} @{{host}}
{% endif %}
{% endfor %}
{% endif %}
{% if user %}
{% for u in user %}
{{user[u]['selectors']}} :omusrmsg:{{u}}
{% endfor %}
{% endif %}
'''
logrotate_configs = '''
{% for file in files %}
{{files[file]['log-file']}} {
missingok
notifempty
create
rotate {{files[file]['max-files']}}
size={{ files[file]['max-size']//1024}}k
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
{% endfor %}
'''
############# config templates end
def get_config():
c = Config()
if not c.exists('system syslog'):
return None
c.set_level('system syslog')
config_data = {
'files' : {},
'console' : {},
'hosts' : {},
'user' : {}
}
#####
# /etc/rsyslog.d/vyos-rsyslog.conf
# 'set system syslog global'
#####
config_data['files'].update(
{
'global' : {
'log-file' : '/var/log/vyos-rsyslog',
'max-size' : 262144,
'action-on-max-size' : '/usr/sbin/logrotate /etc/logrotate.d/vyos-rsyslog',
'selectors' : '*.notice;local7.debug',
'max-files' : '5'
}
}
)
if c.exists('global facility'):
config_data['files']['global']['selectors'] = generate_selectors(c, 'global facility')
if c.exists('global archive size'):
config_data['files']['global']['max-size'] = int(c.return_value('global archive size'))* 1024
if c.exists('global archive files'):
config_data['files']['global']['max-files'] = c.return_value('global archive files')
###
# set system syslog file
###
if c.exists('file'):
filenames = c.list_nodes('file')
for filename in filenames:
config_data['files'].update(
{
filename : {
'log-file' : '/var/log/user/' + filename,
'max-files' : '5',
'action-on-max-size' : '/usr/sbin/logrotate /etc/logrotate.d/' + filename,
'selectors' : '*.err',
'max-size' : 262144
}
}
)
if c.exists('file ' + filename + ' facility'):
config_data['files'][filename]['selectors'] = generate_selectors(c, 'file ' + filename + ' facility')
if c.exists('file ' + filename + ' archive size'):
config_data['files'][filename]['max-size'] = int(c.return_value('file ' + filename + ' archive size'))* 1024
if c.exists('file ' + filename + ' archive files'):
config_data['files'][filename]['max-files'] = c.return_value('file ' + filename + ' archive files')
## set system syslog console
if c.exists('console'):
config_data['console'] = {
'/dev/console' : {
'selectors' : '*.err'
}
}
for f in c.list_nodes('console facility'):
if c.exists('console facility ' + f + ' level'):
config_data['console'] = {
'/dev/console' : {
'selectors' : generate_selectors(c, 'console facility')
}
}
## set system syslog host
if c.exists('host'):
rhosts = c.list_nodes('host')
for rhost in rhosts:
for fac in c.list_nodes('host ' + rhost + ' facility'):
if c.exists('host ' + rhost + ' facility ' + fac + ' protocol'):
proto = c.return_value('host ' + rhost + ' facility ' + fac + ' protocol')
else:
proto = 'udp'
config_data['hosts'].update(
{
rhost : {
'selectors' : generate_selectors(c, 'host ' + rhost + ' facility'),
'proto' : proto
}
}
)
## set system syslog user
if c.exists('user'):
usrs = c.list_nodes('user')
for usr in usrs:
config_data['user'].update(
{
usr : {
'selectors' : generate_selectors(c, 'user ' + usr + ' facility')
}
}
)
return config_data
def generate_selectors(c, config_node):
## protocols and security are being mapped here
## for backward compatibility with old configs
## security and protocol mappings can be removed later
if c.is_tag(config_node):
nodes = c.list_nodes(config_node)
selectors = ""
for node in nodes:
lvl = c.return_value( config_node + ' ' + node + ' level')
if lvl == None:
lvl = "err"
if lvl == 'all':
lvl = '*'
if node == 'all' and node != nodes[-1]:
selectors += "*." + lvl + ";"
elif node == 'all':
selectors += "*." + lvl
elif node != nodes[-1]:
if node == 'protocols':
node = 'local7'
if node == 'security':
node = 'auth'
selectors += node + "." + lvl + ";"
else:
if node == 'protocols':
node = 'local7'
if node == 'security':
node = 'auth'
selectors += node + "." + lvl
return selectors
def generate(c):
tmpl = jinja2.Template(configs, trim_blocks=True)
config_text = tmpl.render(c)
#print (config_text)
with open('/etc/rsyslog.d/vyos-rsyslog.conf', 'w') as f:
f.write(config_text)
## eventually write for each file its own logrotate file, since size is defined it shouldn't matter
tmpl = jinja2.Template(logrotate_configs, trim_blocks=True)
config_text = tmpl.render(c)
#print (config_text)
with open('/etc/logrotate.d/vyos-rsyslog', 'w') as f:
f.write(config_text)
def verify(c):
if c == None:
return None
fac = ['*','auth','authpriv','cron','daemon','kern','lpr','mail','mark','news','protocols','security',\
'syslog','user','uucp','local0','local1','local2','local3','local4','local5','local6','local7']
lvl = ['emerg','alert','crit','err','warning','notice','info','debug','*']
for conf in c:
if c[conf]:
for item in c[conf]:
for s in c[conf][item]['selectors'].split(";"):
f = re.sub("\..*$","",s)
if f not in fac:
print (c[conf])
raise ConfigError('Invalid facility ' + s + ' set in '+ conf + ' ' + item)
l = re.sub("^.+\.","",s)
if l not in lvl:
raise ConfigError('Invalid logging level ' + s + ' set in '+ conf + ' ' + item)
def apply(c):
### vyatta-log.conf is being generated somewhere
### this is just a quick hack to remove the old configfile
if os.path.exists('/etc/rsyslog.d/vyatta-log.conf'):
os.remove('/etc/rsyslog.d/vyatta-log.conf')
os.system("sudo systemctl restart rsyslog >/dev/null")
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
sys.exit(1)

File Metadata

Mime Type
text/x-script.python
Expires
Sat, Oct 17, 12:56 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4376533
Default Alt Text
syslog.py (7 KB)

Event Timeline