Merge "Allow removing apt repositories"
diff --git a/README.rst b/README.rst
index f62a937..1cbc18c 100644
--- a/README.rst
+++ b/README.rst
@@ -328,6 +328,19 @@
               DefaultLimitCPU: 2
               DefaultLimitNPROC: 4
 
+Ensure presence of directory:
+
+.. code-block:: yaml
+
+    linux:
+      system:
+        directory:
+          /tmp/test:
+            user: root
+            group: root
+            mode: 700
+            makedirs: true
+
 Kernel
 ~~~~~~
 
@@ -907,6 +920,44 @@
             netmask: 255.255.255.0
             use_interfaces:
             - eth1
+          br-prv:
+            enabled: true
+            type: ovs_bridge
+            mtu: 65000
+          br-ens7:
+            enabled: true
+            name: br-ens7
+            type: ovs_bridge
+            proto: manual
+            mtu: 9000
+            use_interfaces:
+            - ens7
+          patch-br-ens7-br-prv:
+            enabled: true
+            name: ens7-prv
+            ovs_type: ovs_port
+            type: ovs_port
+            bridge: br-ens7
+            port_type: patch
+            peer: prv-ens7
+            mtu: 65000
+          patch-br-prv-br-ens7:
+            enabled: true
+            name: prv-ens7
+            bridge: br-prv
+            ovs_type: ovs_port
+            type: ovs_port
+            port_type: patch
+            peer: ens7-prv
+            mtu: 65000
+          ens7:
+            enabled: true
+            name: ens7
+            proto: manual
+            ovs_port_type: OVSPort
+            type: ovs_port
+            ovs_bridge: br-ens7
+            bridge: br-ens7
 
 Debian manual proto interfaces
 
diff --git a/linux/files/ovs_port b/linux/files/ovs_port
index 1c807ca..222ca8e 100644
--- a/linux/files/ovs_port
+++ b/linux/files/ovs_port
@@ -1,7 +1,7 @@
 auto {{ port_name }}
 allow-{{ port.bridge }} {{ port_name }}
 iface {{ port_name }} inet {{ port.get('proto', 'manual') }}
-ovs_type OVSIntPort
+ovs_type {{ port.get('ovs_port_type', 'OVSIntPort') }}
 mtu {{ port.get('mtu', '1500') }}
 ovs_bridge {{ port.bridge }}
 {%- if port.get('proto', 'manual') == 'static' %}
diff --git a/linux/files/systemd.conf b/linux/files/systemd.conf
index 36e01a5..2663aed 100644
--- a/linux/files/systemd.conf
+++ b/linux/files/systemd.conf
@@ -1,5 +1,5 @@
 {%- from "linux/map.jinja" import system with context -%}
-{%- for section, options in settings.iteritems() -%}
+{%- for section, options in settings.iteritems() %}
 [{{ section }}]
 {%- for option, value in options.iteritems() %}
 {{ option }}={{ value }}
diff --git a/linux/map.jinja b/linux/map.jinja
index 786410e..c623d63 100644
--- a/linux/map.jinja
+++ b/linux/map.jinja
@@ -18,6 +18,7 @@
          },
         'selinux': 'permissive',
         'ca_certs_dir': '/usr/local/share/ca-certificates',
+        'ca_certs_bin': 'update-ca-certificates',
         'atop': {
              'enabled': false,
              'interval': '20',
@@ -45,6 +46,7 @@
          },
         'selinux': 'permissive',
         'ca_certs_dir': '/usr/local/share/ca-certificates',
+        'ca_certs_bin': 'update-ca-certificates',
         'atop': {
              'enabled': false,
              'interval': '20',
@@ -71,7 +73,8 @@
              'pkgs': []
          },
         'selinux': 'permissive',
-        'ca_certs_dir': '/usr/local/share/ca-certificates',
+        'ca_certs_dir': '/etc/pki/ca-trust/source/anchors',
+        'ca_certs_bin': 'update-ca-trust extract',
         'atop': {
              'enabled': false,
              'interval': '20',
@@ -118,7 +121,7 @@
 
 {% set network = salt['grains.filter_by']({
     'Arch': {
-        'pkgs': ['wpa_supplicant', 'dhclient', 'wireless_tools'],
+        'pkgs': ['wpa_supplicant', 'dhclient', 'wireless_tools', 'ifenslave'],
         'bridge_pkgs': ['bridge-utils'],
         'ovs_pkgs': ['openvswitch-switch'],
         'hostname_file': '/etc/hostname',
@@ -135,6 +138,7 @@
         'dhclient_config': '/etc/dhcp/dhclient.conf',
     },
     'Debian': {
+        'pkgs': ['ifenslave'],
         'hostname_file': '/etc/hostname',
         'bridge_pkgs': ['bridge-utils'],
         'ovs_pkgs': ['openvswitch-switch', 'bridge-utils'],
@@ -152,6 +156,7 @@
         'dhclient_config': '/etc/dhcp/dhclient.conf',
     },
     'RedHat': {
+        'pkgs': ['iputils'],
         'bridge_pkgs': ['bridge-utils'],
         'ovs_pkgs': ['openvswitch-switch', 'bridge-utils'],
         'hostname_file': '/etc/sysconfig/network',
diff --git a/linux/meta/fluentd.yml b/linux/meta/fluentd.yml
new file mode 100644
index 0000000..6ee5e4f
--- /dev/null
+++ b/linux/meta/fluentd.yml
@@ -0,0 +1,41 @@
+config:
+  label:
+    systemd:
+      input:
+        systemd:
+          type: systemd
+          tag: systemd.source
+          path: /run/log/journal
+          pos_file: /tmp/fluentd-systemd.pos
+          entry:
+            field_map:
+              MESSAGE: 'Payload'
+              _CMDLINE: 'process'
+              _PID: 'Pid'
+              _COMM: 'programname'
+              _SYSTEMD_UNIT: 'service'
+              syslog_identifier: 'ident'
+              priority: 'Severity'
+            field_map_strict: True
+            fields_strip_underscores: True
+            fields_lowercase: True
+      filter:
+        add_severity_label:
+          tag: systemd.source
+          type: record_transformer
+          enable_ruby: true
+          record:
+            - name: severity_label
+              value: '${ {"TRACE"=>8,"DEBUG"=>7,"INFO"=>6,"NOTICE"=>5,"WARNING"=>4,"ERROR"=>3,"CRITICAL"=>2,"ALERT"=>1,"EMERGENCY"=>0}.key(record["Severity"].to_i) }'
+      match:
+        rewrite_tag:
+          tag: systemd.source
+          type: rewrite_tag_filter
+          rule:
+            - name: service
+              regexp: '^(.*)\.(.*)$'
+              result: __TAG__.$1
+        push_to_default:
+          tag: 'systemd.source.*'
+          type: relabel
+          label: default_output
diff --git a/linux/meta/prometheus.yml b/linux/meta/prometheus.yml
index 88d2cb7..bea6995 100644
--- a/linux/meta/prometheus.yml
+++ b/linux/meta/prometheus.yml
@@ -42,7 +42,7 @@
         description: 'The disk inodes ({{ $labels.path }}) will be full in less than 8 hours on {{ $labels.host }}.'
       {% endraw %}
     SystemDiskInodesFull:
-      if: 'disk_inodes_used / disk_inodes_total >= 99'
+      if: 'disk_inodes_used / disk_inodes_total >= 0.99'
       {% raw %}
       labels:
         severity: critical
@@ -85,7 +85,7 @@
       if: rate(net_drop_in[1m]) > {{ net_rx_dropped_threshold }}
       {% raw %}
       labels:
-        severity: warning
+        severity: critical
         service: system
       annotations:
         summary: 'Too many received packets dropped on {{ $labels.host }} for interface {{ $labels.interface }}'
@@ -95,7 +95,7 @@
       if: rate(net_drop_out[1m]) > {{ net_tx_dropped_threshold }}
       {% raw %}
       labels:
-        severity: warning
+        severity: critical
         service: system
       annotations:
         summary: 'Too many transmitted packets dropped on {{ $labels.host }} for interface {{ $labels.interface }}'
diff --git a/linux/network/dpdk.sls b/linux/network/dpdk.sls
index cadc599..751941c 100644
--- a/linux/network/dpdk.sls
+++ b/linux/network/dpdk.sls
@@ -148,8 +148,10 @@
     - require:
       - cmd: linux_network_dpdk_bridge_interface_{{ interface.bridge }}
 
+  {%- endif %}
+
   {# Multiqueue n_rxq, pmd_rxq_affinity and mtu setup on interfaces #}
-  {%- elif interface.type == 'dpdk_ovs_port' and (interface.n_rxq is defined or interface.mtu is defined or interface.pmd_rxq_affinity is defined) %}
+  {%- if interface.type == 'dpdk_ovs_port' %}
 
   {%- if interface.n_rxq is defined %}
 
diff --git a/linux/network/interface.sls b/linux/network/interface.sls
index e225888..6f37348 100644
--- a/linux/network/interface.sls
+++ b/linux/network/interface.sls
@@ -183,6 +183,15 @@
   {%- for param in network.interface_params %}
   {{ set_param(param, interface) }}
   {%- endfor %}
+  {%- if interface.require_interfaces is defined %}
+  - require:
+    {%- for netif in interface.get('require_interfaces', []) %}
+    - network: linux_interface_{{ netif }}
+    {%- endfor %}
+    {%- for network in interface.get('use_ovs_ports', []) %}
+    - cmd: ovs_port_up_{{ network }}
+    {%- endfor %}
+  {%- endif %}
   {%- if interface.type == 'bridge' %}
   - bridge: {{ interface_name }}
   - delay: 0
@@ -215,6 +224,23 @@
 
 {%- endif %}
 
+{%- if salt['grains.get']('saltversion') < '2017.7' %}
+# TODO(ddmitriev): Remove this 'if .. endif' block completely when
+# switched to salt version 2017.7 that has the same functionality.
+{%- if interface.type == 'bond' and interface.enabled == True %}
+linux_bond_interface_{{ interface_name }}:
+  cmd.run:
+  - name: ifenslave {{ interface_name }} {{ interface.slaves }}
+  - require:
+    - network: linux_interface_{{ interface_name }}
+  - onchanges:
+    - network: linux_interface_{{ interface_name }}
+    {%- for network in  interface.slaves.split() %}
+    - network: linux_interface_{{ network }}
+    {%- endfor %}
+{%- endif %}
+{%- endif %}
+
 {%- for network in interface.get('use_ovs_ports', []) %}
 
 remove_interface_{{ network }}_line1:
diff --git a/linux/system/certificate.sls b/linux/system/certificate.sls
index f9f39d4..ffa20c4 100644
--- a/linux/system/certificate.sls
+++ b/linux/system/certificate.sls
@@ -35,7 +35,7 @@
 
 update_certificates:
   cmd.wait:
-  - name: update-ca-certificates
+  - name: {{ system.ca_certs_bin }}
 
 {%- endif %}
 
diff --git a/linux/system/directory.sls b/linux/system/directory.sls
new file mode 100644
index 0000000..f53a870
--- /dev/null
+++ b/linux/system/directory.sls
@@ -0,0 +1,15 @@
+{%- from "linux/map.jinja" import system with context %}
+
+{%- for name, dir in system.directory.iteritems() %}
+
+{{ dir.name|default(name) }}:
+  file.directory:
+    {%- if dir %}
+      {%- for key, value in dir.iteritems() %}
+    - {{ key }}: {{ value }}
+      {%- endfor %}
+    {%- else %}
+    - name: {{ name }}
+    {%- endif %}
+
+{%- endfor %}
diff --git a/linux/system/init.sls b/linux/system/init.sls
index 2f379f4..4dc1a8c 100644
--- a/linux/system/init.sls
+++ b/linux/system/init.sls
@@ -96,3 +96,6 @@
 {%- if system.systemd is defined %}
 - linux.system.systemd
 {%- endif %}
+{%- if system.directory is defined %}
+- linux.system.directory
+{%- endif %}
diff --git a/linux/system/job.sls b/linux/system/job.sls
index 5037ff7..09ae0de 100644
--- a/linux/system/job.sls
+++ b/linux/system/job.sls
@@ -1,12 +1,16 @@
 {%- from "linux/map.jinja" import system with context %}
 {%- if system.enabled %}
 
+include:
+- linux.system.user
+
 {%- for name, job in system.job.iteritems() %}
 
 linux_job_{{ job.command }}:
   {%- if job.enabled|default(True) %}
   cron.present:
-    - name: {{ job.command }}
+    - name: >
+        {{ job.command }}
     {%- if job.get('identifier', True) %}
     - identifier: {{ job.get('identifier', job.get('name', name)) }}
     {%- endif %}
diff --git a/linux/system/motd.sls b/linux/system/motd.sls
index e1450c3..f6cdc47 100644
--- a/linux/system/motd.sls
+++ b/linux/system/motd.sls
@@ -10,15 +10,28 @@
 
 {%- else %}
 
+{%- if grains.os == 'Ubuntu' %}
 package_update_motd:
   pkg.installed:
     - name: update-motd
+    - require_in:
+      - file: /etc/update-motd.d
+{%- endif %}
 
 /etc/update-motd.d:
   file.directory:
     - clean: true
-    - require:
-      - pkg: package_update_motd
+
+{%- if grains.oscodename == "jessie" %}
+motd_fix_pam_sshd:
+  file.replace:
+    - name: /etc/pam.d/sshd
+    - pattern: "/run/motd.dynamic"
+    - repl: "/run/motd"
+{%- endif %}
+
+/etc/motd:
+  file.absent
 
 {%- for motd in system.motd %}
 {%- set motd_index = loop.index %}
diff --git a/linux/system/repo.sls b/linux/system/repo.sls
index 907f4cf..a7a311e 100644
--- a/linux/system/repo.sls
+++ b/linux/system/repo.sls
@@ -106,7 +106,7 @@
 linux_repo_{{ name }}:
   pkgrepo.managed:
   {%- if repo.ppa is defined %}
-  - ppa: {{ ppa }}
+  - ppa: {{ repo.ppa }}
   {%- else %}
   - human_name: {{ name }}
   - name: {{ repo.source }}
diff --git a/linux/system/selinux.sls b/linux/system/selinux.sls
index ff1d84d..5bbd815 100644
--- a/linux/system/selinux.sls
+++ b/linux/system/selinux.sls
@@ -1,5 +1,5 @@
 {%- from "linux/map.jinja" import system with context %}
-{%- if system.enabled %}
+{%- if system.selinux is defined %}
 
 include:
 - linux.system.repo
@@ -7,24 +7,22 @@
 {%- if grains.os_family == 'RedHat' %}
 
 {%- if system.selinux == 'disabled' %}
+  {%- set mode = 'permissive' %}
+{%- else %}
+  {%- set mode = system.selinux %}
+{%- endif %}
 
 selinux_config:
   cmd.run:
-  - names:
-    - "sed -i 's/enforcing/disabled/g' /etc/selinux/config; setenforce 0"
-    - "sed -i 's/permissive/disabled/g' /etc/selinux/config; setenforce 0"
-  - unless: cat '/etc/selinux/config' | grep 'SELINUX=disabled'
-
-{%- else %}
-
-selinux_config:
-  selinux.mode:
-  - name: {{ system.get('selinux', 'permissive') }}
+  - name: "sed -i 's/SELINUX=[a-z][a-z]*$/SELINUX={{ system.selinux }}/' /etc/selinux/config"
+  - unless: grep 'SELINUX={{ system.selinux }}' /etc/selinux/config
   - require:
     - pkg: linux_repo_prereq_pkgs
 
-{%- endif %}
+{{ mode }}:
+  selinux.mode
 
 {%- endif %}
 
 {%- endif %}
+
diff --git a/metadata/service/support.yml b/metadata/service/support.yml
index 031dcfb..a59c6f0 100644
--- a/metadata/service/support.yml
+++ b/metadata/service/support.yml
@@ -15,3 +15,5 @@
         enabled: true
       grafana:
         enabled: true
+      fluentd:
+        enabled: true
diff --git a/tests/pillar/network_openvswitch_dpdk.sls b/tests/pillar/network_openvswitch_dpdk.sls
index 73623d6..fa96cb9 100644
--- a/tests/pillar/network_openvswitch_dpdk.sls
+++ b/tests/pillar/network_openvswitch_dpdk.sls
@@ -39,3 +39,11 @@
       br-prv:
         enabled: true
         type: dpdk_ovs_bridge
+      dummy0:
+        enabled: true
+        name: dummy0
+        proto: manual
+        ovs_port_type: OVSIntPort
+        type: ovs_port
+        ovs_bridge: br-prv
+        bridge: br-prv
diff --git a/tests/pillar/system.sls b/tests/pillar/system.sls
index 411323c..cba1aea 100644
--- a/tests/pillar/system.sls
+++ b/tests/pillar/system.sls
@@ -7,6 +7,9 @@
     environment: prd
     hostname: system.pillar.local
     purge_repos: true
+    directory:
+      /tmp/test:
+        makedirs: true
     apparmor:
       enabled: false
     haveged: