diff --git a/playbooks/pre.yml b/playbooks/pre.yml index ee7e928a..be973f65 100644 --- a/playbooks/pre.yml +++ b/playbooks/pre.yml @@ -66,6 +66,9 @@ - role: helper/ntp tags: [ntp] + - role: helper/logs + tags: [logs] + - role: helper/mkfs tags: [mkfs] diff --git a/roles/helper/logs/README.md b/roles/helper/logs/README.md new file mode 100644 index 00000000..37638802 --- /dev/null +++ b/roles/helper/logs/README.md @@ -0,0 +1,77 @@ +Role: opennebula.deploy.helper.logs +=================================== + +A role that configures logrotate and rsyslog (when available). + +Requirements +------------ + +N/A + +Role Variables +-------------- + +| Name | Type | Default | Example | Description | +|------------------------------|--------|-----------------------|---------------|------------------------------------| +| `logrotate` | `dict` | `{}` | (check below) | User config for logrotate subrole. | +| `logrotate_defaults` | `dict` | (check role defaults) | (check below) | | +| `rsyslog` | `dict` | `{}` | (check below) | User config for rsyslog subrole. | +| `rsyslog_defaults` | `dict` | (check role defaults) | (check below) | | +| `rsyslog_collector.target` | `str` | undefined | (check below) | Destination host to send logs to. | +| `rsyslog_collector.protocol` | `str` | `tcp` | (check below) | Protcol to use for sending logs. | +| `rsyslog_collector.port` | `str` | `514` | (check below) | Destination port to send logs to. | + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + + - hosts: node + vars: + logrotate_defaults: {} # disable defaults + logrotate: + openvswitch: + managed: true # can be omitted as it's true by default + paths: + - /var/log/openvswitch/*.log + config: + - su root root + - daily + - rotate 30 + - missingok + - notifempty + - compress + - delaycompress + - dateext + - sharedscripts + - postrotate: |- + if [ -d /run/openvswitch ]; then + for ctl in /run/openvswitch/*.ctl; do + ovs-appctl -t "$ctl" vlog/reopen 2>/dev/null ||: + done + fi + rsyslog: + 90-kernel: + # Replace default path /var/log/kern.log + config: | + module(load="imklog") + kern.info /var/log/asd.log + # Enable log forwarding + rsyslog_collector: + target: 10.11.12.13 + roles: + - role: opennebula.deploy.helper.facts + - role: opennebula.deploy.helper.logs + +License +------- + +Apache-2.0 + +Author Information +------------------ + +[OpenNebula Systems](https://opennebula.io/) diff --git a/roles/helper/logs/logrotate/defaults/main.yml b/roles/helper/logs/logrotate/defaults/main.yml new file mode 100644 index 00000000..5b54f102 --- /dev/null +++ b/roles/helper/logs/logrotate/defaults/main.yml @@ -0,0 +1,24 @@ +--- +logrotate: {} + +logrotate_defaults: + rsyslog: + # managed: true + paths: + - /var/log/cron + - /var/log/maillog + - /var/log/messages + - /var/log/secure + - /var/log/spooler + - /var/log/kern.log + config: + - daily + - rotate 30 + - missingok + - notifempty + - compress + - delaycompress + - dateext + - sharedscripts + - postrotate: |- + /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 ||: diff --git a/roles/helper/logs/logrotate/meta/main.yml b/roles/helper/logs/logrotate/meta/main.yml new file mode 100644 index 00000000..8fe6dc20 --- /dev/null +++ b/roles/helper/logs/logrotate/meta/main.yml @@ -0,0 +1,3 @@ +--- +collections: + - opennebula.deploy diff --git a/roles/helper/logs/logrotate/tasks/main.yml b/roles/helper/logs/logrotate/tasks/main.yml new file mode 100644 index 00000000..50a8fe40 --- /dev/null +++ b/roles/helper/logs/logrotate/tasks/main.yml @@ -0,0 +1,58 @@ +--- +- name: Merge logrotate dict with defaults + ansible.builtin.set_fact: + logrotate: >- + {{ logrotate_defaults | combine(logrotate, recursive=true) }} + +- when: _managed + vars: + _managed: >- + {{ (logrotate.values() | selectattr('managed', 'undefined') + | count > 0) + or + (logrotate.values() | selectattr('managed', 'defined') + | map(attribute='managed') + | map('bool') + | select + | count > 0) }} + block: + - name: Stat /etc/logrotate.d/ + ansible.builtin.stat: + path: /etc/logrotate.d/ + get_attributes: false + get_checksum: false + get_mime: false + register: stat_logrotate_d + + - when: + - stat_logrotate_d.stat.exists + - stat_logrotate_d.stat.isdir + block: + - name: Render logrotate configs + ansible.builtin.copy: + dest: "/etc/logrotate.d/{{ item }}" + owner: 0 + group: 0 + mode: u=rw,go=r + content: "{{ _content }}" + vars: + _content: | + # managed by one-deploy + {{ logrotate[item].paths | join(' ') }} { + {% for d in logrotate[item].config %} + {% if d is mapping %} + {% for k, v in d.items() %} + {{ k }} + {% filter indent(width=4, first=true) %} + {{ v }} + {% endfilter %} + endscript + {% endfor %} + {% else %} + {{ d }} + {% endif %} + {% endfor %} + } + when: + - logrotate[item].managed | d(true) | bool + loop: "{{ logrotate.keys() }}" diff --git a/roles/helper/logs/rsyslog/defaults/main.yml b/roles/helper/logs/rsyslog/defaults/main.yml new file mode 100644 index 00000000..a0f70062 --- /dev/null +++ b/roles/helper/logs/rsyslog/defaults/main.yml @@ -0,0 +1,46 @@ +--- +# EXAMPLE: +# rsyslog_collector: +# target: 10.11.12.13 # mandatory +# protocol: tcp # optional +# port: 514 # optional +rsyslog_collector: {} + +rsyslog: {} + +rsyslog_defaults: + 90-kernel: + # managed: true + config: | + module(load="imklog") + kern.info /var/log/kern.log + # NOTE: By default "everything" is forwarded. + # You can redefine the whole rsyslog dictionary to get custom behavior. + 98-forward: + managed: "{{ rsyslog_collector.target is defined and rsyslog_collector.target is truthy }}" + config: | + action( + # output module for forwarding messages + type="omfwd" + + # 1gb space limit (use as much as possible) + queue.maxdiskspace="1g" + + # save messages to disk on shutdown + queue.saveonshutdown="on" + + # run asynchronously + queue.type="LinkedList" + + # infinite retries if host is down + action.resumeRetryCount="-1" + + # destination server + target="{{ rsyslog_collector.target | d() }}" + + # transport protocol + protocol="{{ rsyslog_collector.protocol | d('tcp') }}" + + # port on the remote syslog server + port="{{ rsyslog_collector.port | d('514') }}" + ) diff --git a/roles/helper/logs/rsyslog/meta/main.yml b/roles/helper/logs/rsyslog/meta/main.yml new file mode 100644 index 00000000..8fe6dc20 --- /dev/null +++ b/roles/helper/logs/rsyslog/meta/main.yml @@ -0,0 +1,3 @@ +--- +collections: + - opennebula.deploy diff --git a/roles/helper/logs/rsyslog/tasks/main.yml b/roles/helper/logs/rsyslog/tasks/main.yml new file mode 100644 index 00000000..930f8b77 --- /dev/null +++ b/roles/helper/logs/rsyslog/tasks/main.yml @@ -0,0 +1,53 @@ +--- +- name: Merge rsyslog dict with defaults + ansible.builtin.set_fact: + rsyslog: >- + {{ rsyslog_defaults | combine(rsyslog, recursive=true) }} + +- when: _managed + vars: + _managed: >- + {{ (rsyslog.values() | selectattr('managed', 'undefined') + | count > 0) + or + (rsyslog.values() | selectattr('managed', 'defined') + | map(attribute='managed') + | map('bool') + | select + | count > 0) }} + block: + - name: Stat /etc/rsyslog.d/ + ansible.builtin.stat: + path: /etc/rsyslog.d/ + get_attributes: false + get_checksum: false + get_mime: false + register: stat_rsyslog_d + + - when: + - stat_rsyslog_d.stat.exists + - stat_rsyslog_d.stat.isdir + block: + - name: Render rsyslog configs + ansible.builtin.copy: + dest: "/etc/rsyslog.d/{{ item }}.conf" + owner: 0 + group: 0 + mode: u=rw,go=r + content: "{{ _content }}" + vars: + _content: | + # managed by one-deploy + {{ rsyslog[item].config }} + when: + - rsyslog[item].managed | d(true) | bool + loop: "{{ rsyslog.keys() }}" + register: copy_rsyslog_configs + + - name: Restart rsyslog (NOW) + ansible.builtin.service: + name: rsyslog.service + state: restarted + when: + - copy_rsyslog_configs is defined + - copy_rsyslog_configs is changed diff --git a/roles/helper/logs/tasks/main.yml b/roles/helper/logs/tasks/main.yml new file mode 100644 index 00000000..91d15404 --- /dev/null +++ b/roles/helper/logs/tasks/main.yml @@ -0,0 +1,6 @@ +--- +- ansible.builtin.include_role: + name: helper/logs/logrotate + +- ansible.builtin.include_role: + name: helper/logs/rsyslog diff --git a/roles/kvm/tasks/libvirt.yml b/roles/kvm/tasks/libvirt.yml index 65950d3a..5284eec2 100644 --- a/roles/kvm/tasks/libvirt.yml +++ b/roles/kvm/tasks/libvirt.yml @@ -1,9 +1,16 @@ --- -- name: Ensure each libvirtd uses distinct UUID +- name: Configure libvirtd (UUID + logging) ansible.builtin.lineinfile: path: /etc/libvirt/libvirtd.conf - regexp: '^[#\s]*host_uuid\s*=.*$' - line: 'host_uuid = "{{ inventory_hostname | to_uuid }}"' + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + loop: + - regexp: '^[#\s]*host_uuid\s*=.*$' + line: 'host_uuid = "{{ inventory_hostname | to_uuid }}"' + - regexp: '^[#\s]*log_filters\s*=.*$' + line: 'log_filters = "3:libvirt 3:qemu"' + - regexp: '^[#\s]*log_outputs\s*=.*$' + line: 'log_outputs = "2:syslog:libvirtd"' register: lineinfile - name: Restart libvirtd (NOW) diff --git a/roles/openvswitch/tasks/main.yml b/roles/openvswitch/tasks/main.yml index 9c21bb7b..8589f912 100644 --- a/roles/openvswitch/tasks/main.yml +++ b/roles/openvswitch/tasks/main.yml @@ -287,11 +287,57 @@ path: /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk register: alternatives_ovs_vswitchd + - name: Configure logrotate for OVS + ansible.builtin.include_role: + name: helper/logs/logrotate + vars: + logrotate_defaults: {} + logrotate: + openvswitch: + paths: + - /var/log/openvswitch/*.log + config: + - su root root + - daily + - rotate 30 + - missingok + - notifempty + - compress + - delaycompress + - dateext + - sharedscripts + - postrotate: |- + if [ -d /run/openvswitch ]; then + for ctl in /run/openvswitch/*.ctl; do + ovs-appctl -t "$ctl" vlog/reopen 2>/dev/null ||: + done + fi + + - name: Create systemd drop-in for ovs-vswitchd.service (mkdir) + ansible.builtin.file: + path: /etc/systemd/system/ovs-vswitchd.service.d + state: directory + owner: 0 + group: 0 + mode: u=rwx,go=rx + + - name: Create systemd drop-in for ovs-vswitchd.service + ansible.builtin.copy: + dest: /etc/systemd/system/ovs-vswitchd.service.d/override.conf + owner: 0 + group: 0 + mode: u=rw,go=r + content: | + [Service] + ExecStartPost=/bin/sleep 2 + ExecStartPost=/usr/bin/ovs-appctl -t ovs-vswitchd vlog/set syslog:info + register: copy_override_conf + - name: Enable / (Re)Start OVS (NOW) ansible.builtin.systemd_service: + daemon_reload: "{{ _changed }}" name: "{{ _specific[ansible_os_family] }}" - state: >- - {{ 'restarted' if _changed else 'started' }} + state: "{{ 'restarted' if _changed else 'started' }}" enabled: true vars: _specific: @@ -299,9 +345,11 @@ RedHat: openvswitch.service Suse: openvswitch.service _changed: >- - {{ (alternatives_ovs_vswitchd is defined) - and - (alternatives_ovs_vswitchd is changed) }} + {{ (copy_override_conf is changed) + or + ((alternatives_ovs_vswitchd is defined) + and + (alternatives_ovs_vswitchd is changed)) }} - name: Install OVS-related scripts ansible.builtin.template: