From 870238d9b375f59bcf3890060472b68fc51498ac Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 21 Mar 2022 16:52:18 +0100
Subject: [PATCH] Add printer monitoring

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/prometheus.yml                     |   4 -
 group_vars/snmp.yml                           |   5 +
 host_vars/helloworld.adm.crans.org.yml        |   3 +
 host_vars/monitoring.adm.crans.org.yml        |  19 +
 hosts                                         |   7 +
 plays/monitoring.yml                          |  16 +-
 roles/prometheus-snmp-exporter/tasks/main.yml |   2 +-
 .../templates/prometheus/snmp.yml.j2          | 495 ++++++++++++++++++
 .../templates/prometheus/alert.rules.yml.j2   |  86 +++
 9 files changed, 628 insertions(+), 9 deletions(-)
 create mode 100644 group_vars/snmp.yml

diff --git a/group_vars/prometheus.yml b/group_vars/prometheus.yml
index 60449558..ccd9a040 100644
--- a/group_vars/prometheus.yml
+++ b/group_vars/prometheus.yml
@@ -1,10 +1,6 @@
 ---
 glob_prometheus: {}
 
-glob_snmp_exporter:
-  procurve_password: "{{ vault.snmp_procurve_password }}"
-  unifi_password: "{{ vault.snmp_unifi_password }}"
-
 glob_ninjabot:
   config:
     nick: monitoring
diff --git a/group_vars/snmp.yml b/group_vars/snmp.yml
new file mode 100644
index 00000000..af2b5759
--- /dev/null
+++ b/group_vars/snmp.yml
@@ -0,0 +1,5 @@
+---
+glob_snmp_exporter:
+  listen_address: 127.0.0.1:9116
+  procurve_password: "{{ vault.snmp_procurve_password }}"
+  unifi_password: "{{ vault.snmp_unifi_password }}"
diff --git a/host_vars/helloworld.adm.crans.org.yml b/host_vars/helloworld.adm.crans.org.yml
index 92076e1a..345bc792 100644
--- a/host_vars/helloworld.adm.crans.org.yml
+++ b/host_vars/helloworld.adm.crans.org.yml
@@ -2,3 +2,6 @@
 interfaces:
   adm: ens18
   srv_nat: ens19
+
+loc_snmp_exporter:
+  listen_address: "{{ query('ldap', 'ip', 'helloworld', 'adm') | ipv4 | first }}:9116"
diff --git a/host_vars/monitoring.adm.crans.org.yml b/host_vars/monitoring.adm.crans.org.yml
index 17cbdfb7..8850d61a 100644
--- a/host_vars/monitoring.adm.crans.org.yml
+++ b/host_vars/monitoring.adm.crans.org.yml
@@ -110,3 +110,22 @@ loc_prometheus:
             target_label: instance
           - replacement: '127.0.0.1:9116'
             target_label: __address__
+
+  printer_snmp:
+    file: targets_printer.json
+    targets: ["printer.lp.crans.org"]
+    config:
+      - job_name: printer_snmp
+        static_configs:
+          - targets: ["printer.lp.crans.org"]
+        metrics_path: '/snmp'
+        params:
+          module:
+            - printer_mib
+        relabel_configs:
+          - source_labels: [__address__]
+            target_label: __param_target
+          - source_labels: [__param_target]
+            target_label: instance
+          - replacement: 172.16.10.131:9116
+            target_label: __address__
diff --git a/hosts b/hosts
index c16b2cfa..8f3f36cb 100644
--- a/hosts
+++ b/hosts
@@ -188,6 +188,9 @@ helloworld.adm.crans.org
 monitoring.adm.crans.org
 fyre.cachan-adm.crans.org
 
+[prometheus_alertmanager]
+monitoring.adm.crans.org
+
 [radius]
 routeur-gulp.cachan-adm.crans.org
 
@@ -239,6 +242,10 @@ eclat.adm.crans.org
 gulp.cachan-adm.crans.org
 tealc.adm.crans.org
 
+[snmp]
+monitoring.adm.crans.org
+helloworld.adm.crans.org
+
 [unifi]
 unifi.cachan-adm.crans.org
 
diff --git a/plays/monitoring.yml b/plays/monitoring.yml
index 10c3cd8f..156e3c1f 100755
--- a/plays/monitoring.yml
+++ b/plays/monitoring.yml
@@ -5,13 +5,15 @@
 - hosts: prometheus
   vars:
     prometheus: "{{ glob_prometheus | default({}) | combine(loc_prometheus | default({})) }}"
-    alertmanager: "{{ glob_alertmanager | default({}) | combine(loc_alertmanager | default({})) }}"
-    snmp_exporter: "{{ glob_snmp_exporter | default({}) | combine(loc_snmp_exporter | default({})) }}"
-    ninjabot: "{{ glob_ninjabot | default({}) | combine(loc_ninjabot | default({})) }}"
   roles:
     - prometheus
+
+- hosts: prometheus_alertmanager
+  vars:
+    alertmanager: "{{ glob_alertmanager | default({}) | combine(loc_alertmanager | default({})) }}"
+    ninjabot: "{{ glob_ninjabot | default({}) | combine(loc_ninjabot | default({})) }}"
+  roles:
     - prometheus-alertmanager
-    - prometheus-snmp-exporter
     - ninjabot
 
 # Deploy Grafana on monitoring server
@@ -25,6 +27,12 @@
   roles:
     - prometheus-blackbox-exporter
 
+- hosts: snmp
+  vars:
+    snmp_exporter: "{{ glob_snmp_exporter | default({}) | combine(loc_snmp_exporter | default({})) }}"
+  roles:
+    - prometheus-snmp-exporter
+
 # Monitor all hosts
 - hosts: server
   vars:
diff --git a/roles/prometheus-snmp-exporter/tasks/main.yml b/roles/prometheus-snmp-exporter/tasks/main.yml
index 8ee759e1..74671baf 100644
--- a/roles/prometheus-snmp-exporter/tasks/main.yml
+++ b/roles/prometheus-snmp-exporter/tasks/main.yml
@@ -11,7 +11,7 @@
   lineinfile:
     path: /etc/default/prometheus-snmp-exporter
     regexp: '^ARGS='
-    line: "ARGS=\"--web.listen-address=127.0.0.1:9116\""
+    line: "ARGS=\"--web.listen-address={{ snmp_exporter.listen_address }}\""
   notify: Restart prometheus-snmp-exporter
 
 # This file store SNMP OIDs
diff --git a/roles/prometheus-snmp-exporter/templates/prometheus/snmp.yml.j2 b/roles/prometheus-snmp-exporter/templates/prometheus/snmp.yml.j2
index 5455ae6f..1a7d1fda 100644
--- a/roles/prometheus-snmp-exporter/templates/prometheus/snmp.yml.j2
+++ b/roles/prometheus-snmp-exporter/templates/prometheus/snmp.yml.j2
@@ -702,3 +702,498 @@ ilo:
     auth_protocol: SHA
     priv_protocol: AES
     priv_password: 21rW6LHShmgdHsdPQXHP
+
+printer_mib:
+  walk:
+  - 1.3.6.1.2.1.25.3.5.1.1
+  - 1.3.6.1.2.1.43.11.1.1.5
+  - 1.3.6.1.2.1.43.11.1.1.6
+  - 1.3.6.1.2.1.43.11.1.1.8
+  - 1.3.6.1.2.1.43.11.1.1.9
+  - 1.3.6.1.2.1.43.5.1.1.13
+  - 1.3.6.1.2.1.43.5.1.1.16
+  - 1.3.6.1.2.1.43.5.1.1.17
+  - 1.3.6.1.2.1.43.5.1.1.18
+  - 1.3.6.1.2.1.43.5.1.1.19
+  - 1.3.6.1.2.1.43.5.1.1.3
+  - 1.3.6.1.2.1.43.6.1.1.3
+  - 1.3.6.1.4.1.641.1.0.2
+  - 1.3.6.1.4.1.641.1.0.3
+  - 1.3.6.1.4.1.641.1.0.4
+  - 1.3.6.1.4.1.641.1.0.5
+  - 1.3.6.1.4.1.641.1.0.8
+  - 1.3.6.1.4.1.641.2.1.3.1.3
+  - 1.3.6.1.4.1.641.2.1.3.1.4
+  - 1.3.6.1.4.1.641.2.1.3.1.5
+  - 1.3.6.1.4.1.641.2.1.3.1.6
+  - 1.3.6.1.4.1.641.2.1.3.1.7
+  - 1.3.6.1.4.1.641.2.1.3.1.8
+  - 1.3.6.1.4.1.641.2.1.3.1.9
+  - 1.3.6.1.4.1.641.6.4.2.3.1.3
+  - 1.3.6.1.4.1.641.6.5.1.1.4
+  - 1.3.6.1.4.1.641.6.5.1.1.5
+  - 1.3.6.1.4.1.641.6.5.1.1.6
+  get:
+  - 1.3.6.1.2.1.1.3.0
+  - 1.3.6.1.4.1.641.2.1.5.1.0
+  - 1.3.6.1.4.1.641.2.1.5.2.0
+  - 1.3.6.1.4.1.641.2.1.5.3.0
+  metrics:
+  - name: sysUpTime
+    oid: 1.3.6.1.2.1.1.3
+    type: gauge
+    help: The time (in hundredths of a second) since the network management portion
+      of the system was last re-initialized. - 1.3.6.1.2.1.1.3
+  - name: hrPrinterStatus
+    oid: 1.3.6.1.2.1.25.3.5.1.1
+    type: EnumAsStateSet
+    help: The current status of this printer device. - 1.3.6.1.2.1.25.3.5.1.1
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    enum_values:
+      1: other
+      2: unknown
+      3: idle
+      4: printing
+      5: warmup
+  - name: prtMarkerSuppliesType
+    oid: 1.3.6.1.2.1.43.11.1.1.5
+    type: gauge
+    help: The type of this supply. - 1.3.6.1.2.1.43.11.1.1.5
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    - labelname: prtMarkerSuppliesIndex
+      type: gauge
+    lookups:
+    - labels:
+      - hrDeviceIndex
+      - prtMarkerSuppliesIndex
+      labelname: prtMarkerSuppliesType
+      oid: 1.3.6.1.2.1.43.11.1.1.5
+      type: gauge
+    enum_values:
+      1: other
+      2: unknown
+      3: toner
+      4: wasteToner
+      5: ink
+      6: inkCartridge
+      7: inkRibbon
+      8: wasteInk
+      9: opc
+      10: developer
+      11: fuserOil
+      12: solidWax
+      13: ribbonWax
+      14: wasteWax
+      15: fuser
+      16: coronaWire
+      17: fuserOilWick
+      18: cleanerUnit
+      19: fuserCleaningPad
+      20: transferUnit
+      21: tonerCartridge
+      22: fuserOiler
+      23: water
+      24: wasteWater
+      25: glueWaterAdditive
+      26: wastePaper
+      27: bindingSupply
+      28: bandingSupply
+      29: stitchingWire
+      30: shrinkWrap
+      31: paperWrap
+      32: staples
+      33: inserts
+      34: covers
+      35: matteToner
+      36: matteInk
+  - name: prtMarkerSuppliesDescription
+    oid: 1.3.6.1.2.1.43.11.1.1.6
+    type: DisplayString
+    help: The description of this supply container/receptacle in the localization
+      specified by prtGeneralCurrentLocalization. - 1.3.6.1.2.1.43.11.1.1.6
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    - labelname: prtMarkerSuppliesIndex
+      type: gauge
+    lookups:
+    - labels:
+      - hrDeviceIndex
+      - prtMarkerSuppliesIndex
+      labelname: prtMarkerSuppliesType
+      oid: 1.3.6.1.2.1.43.11.1.1.5
+      type: gauge
+  - name: prtMarkerSuppliesMaxCapacity
+    oid: 1.3.6.1.2.1.43.11.1.1.8
+    type: gauge
+    help: The maximum capacity of this supply container/receptacle expressed in prtMarkerSuppliesSupplyUnit
+      - 1.3.6.1.2.1.43.11.1.1.8
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    - labelname: prtMarkerSuppliesIndex
+      type: gauge
+    lookups:
+    - labels:
+      - hrDeviceIndex
+      - prtMarkerSuppliesIndex
+      labelname: prtMarkerSuppliesType
+      oid: 1.3.6.1.2.1.43.11.1.1.5
+      type: gauge
+  - name: prtMarkerSuppliesLevel
+    oid: 1.3.6.1.2.1.43.11.1.1.9
+    type: gauge
+    help: The current level if this supply is a container; the remaining space if
+      this supply is a receptacle - 1.3.6.1.2.1.43.11.1.1.9
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    - labelname: prtMarkerSuppliesIndex
+      type: gauge
+    lookups:
+    - labels:
+      - hrDeviceIndex
+      - prtMarkerSuppliesIndex
+      labelname: prtMarkerSuppliesType
+      oid: 1.3.6.1.2.1.43.11.1.1.5
+      type: gauge
+  - name: prtConsoleDisable
+    oid: 1.3.6.1.2.1.43.5.1.1.13
+    type: EnumAsStateSet
+    help: This value indicates how input is (or is not) accepted from the operator
+      console - 1.3.6.1.2.1.43.5.1.1.13
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    enum_values:
+      3: enabled
+      4: disabled
+  - name: prtGeneralPrinterName
+    oid: 1.3.6.1.2.1.43.5.1.1.16
+    type: DisplayString
+    help: An administrator-specified name for this printer - 1.3.6.1.2.1.43.5.1.1.16
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+  - name: prtGeneralSerialNumber
+    oid: 1.3.6.1.2.1.43.5.1.1.17
+    type: DisplayString
+    help: A recorded serial number for this device that indexes some type device catalog
+      or inventory - 1.3.6.1.2.1.43.5.1.1.17
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+  - name: prtAlertCriticalEvents
+    oid: 1.3.6.1.2.1.43.5.1.1.18
+    type: counter
+    help: A running counter of the number of critical alert events that have been
+      recorded in the alert table - 1.3.6.1.2.1.43.5.1.1.18
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+  - name: prtAlertAllEvents
+    oid: 1.3.6.1.2.1.43.5.1.1.19
+    type: counter
+    help: A running counter of the total number of alert event entries (critical and
+      non-critical) that have been recorded in the alert table - 1.3.6.1.2.1.43.5.1.1.19
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+  - name: prtGeneralReset
+    oid: 1.3.6.1.2.1.43.5.1.1.3
+    type: EnumAsStateSet
+    help: Setting this value to 'powerCycleReset', 'resetToNVRAM', or 'resetToFactoryDefaults'
+      will result in the resetting of the printer - 1.3.6.1.2.1.43.5.1.1.3
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    enum_values:
+      3: notResetting
+      4: powerCycleReset
+      5: resetToNVRAM
+      6: resetToFactoryDefaults
+  - name: prtCoverStatus
+    oid: 1.3.6.1.2.1.43.6.1.1.3
+    type: EnumAsStateSet
+    help: The status of this cover sub-unit. - 1.3.6.1.2.1.43.6.1.1.3
+    indexes:
+    - labelname: hrDeviceIndex
+      type: gauge
+    - labelname: prtCoverIndex
+      type: gauge
+    enum_values:
+      1: other
+      2: unknown
+      3: coverOpen
+      4: coverClosed
+      5: interlockOpen
+      6: interlockClosed
+  - name: prtgenStatusOutHopFull
+    oid: 1.3.6.1.4.1.641.2.1.3.1.3
+    type: gauge
+    help: The printer's current output hopper status. - 1.3.6.1.4.1.641.2.1.3.1.3
+    indexes:
+    - labelname: prtgenStatPrinterIndex
+      type: gauge
+    enum_values:
+      1: notFull
+      2: full
+      3: unknown
+  - name: prtgenStatusInputEmpty
+    oid: 1.3.6.1.4.1.641.2.1.3.1.4
+    type: gauge
+    help: The printer's current active input paper tray status. - 1.3.6.1.4.1.641.2.1.3.1.4
+    indexes:
+    - labelname: prtgenStatPrinterIndex
+      type: gauge
+    enum_values:
+      1: notEmpty
+      2: empty
+      3: unknown
+  - name: prtgenStatusPaperJam
+    oid: 1.3.6.1.4.1.641.2.1.3.1.5
+    type: gauge
+    help: The printer's current paper path status. - 1.3.6.1.4.1.641.2.1.3.1.5
+    indexes:
+    - labelname: prtgenStatPrinterIndex
+      type: gauge
+    enum_values:
+      1: notJammed
+      2: jamed
+      3: unknown
+  - name: prtgenStatusTonerError
+    oid: 1.3.6.1.4.1.641.2.1.3.1.6
+    type: gauge
+    help: The printer's current toner supply status. - 1.3.6.1.4.1.641.2.1.3.1.6
+    indexes:
+    - labelname: prtgenStatPrinterIndex
+      type: gauge
+    enum_values:
+      1: noTonerError
+      2: tonerError
+      3: unknown
+  - name: prtgenStatusSrvcReqd
+    oid: 1.3.6.1.4.1.641.2.1.3.1.7
+    type: gauge
+    help: The printer's current service required status. - 1.3.6.1.4.1.641.2.1.3.1.7
+    indexes:
+    - labelname: prtgenStatPrinterIndex
+      type: gauge
+    enum_values:
+      1: noServiceRequired
+      2: serviceRequired
+      3: unknown
+  - name: prtgenStatusDiskError
+    oid: 1.3.6.1.4.1.641.2.1.3.1.8
+    type: gauge
+    help: The printer's current disk sub-system status. - 1.3.6.1.4.1.641.2.1.3.1.8
+    indexes:
+    - labelname: prtgenStatPrinterIndex
+      type: gauge
+    enum_values:
+      1: noDiskError
+      2: diskError
+      3: unknown
+  - name: prtgenStatusCoverOpen
+    oid: 1.3.6.1.4.1.641.2.1.3.1.9
+    type: gauge
+    help: The printer's current cover status. - 1.3.6.1.4.1.641.2.1.3.1.9
+    indexes:
+    - labelname: prtgenStatPrinterIndex
+      type: gauge
+    enum_values:
+      1: noCoverOpen
+      2: coverOpen
+      3: unknown
+  - name: pgTotal
+    oid: 1.3.6.1.4.1.641.2.1.5.1
+    type: counter
+    help: The total number of pages printed. - 1.3.6.1.4.1.641.2.1.5.1
+  - name: pgMono
+    oid: 1.3.6.1.4.1.641.2.1.5.2
+    type: counter
+    help: The number of monochrome pages printed. - 1.3.6.1.4.1.641.2.1.5.2
+  - name: pgColor
+    oid: 1.3.6.1.4.1.641.2.1.5.3
+    type: counter
+    help: The number of color pages printed. - 1.3.6.1.4.1.641.2.1.5.3
+  - name: paperSheetsPaperType
+    oid: 1.3.6.1.4.1.641.6.4.2.3.1.3
+    type: gauge
+    help: The type of the paper - 1.3.6.1.4.1.641.6.4.2.3.1.3
+    indexes:
+    - labelname: deviceIndex
+      type: gauge
+    - labelname: paperSheetsCountIndex
+      type: gauge
+    enum_values:
+      1: unknown
+      2: other
+      3: plain
+      4: cardstock
+      5: transparancy
+      6: recycled
+      7: labels
+      8: vinylLabels
+      9: bond
+      10: letterhead
+      11: preprinted
+      12: colored
+      13: light
+      14: heavy
+      15: roughOrCotton
+      16: envelope
+      17: premimuPlain
+      18: colorLokCertifiedPlain
+      19: lexmarkPerfectFinishPhoto
+      20: lexmarkPhoto
+      21: glossyPhoto
+      22: mattePhoto
+      23: inkjetMatteBrochure
+      24: inkjetGlossyBrochure
+      25: ironOnTransfer
+      32: customtype1
+      33: customtype2
+      34: customtype3
+      35: customtype4
+      36: customtype5
+      37: customtype6
+      38: coatedPaper
+      39: glossy
+      40: photPaper
+      41: greetingCard
+      42: heavyCard
+      43: roughEnvelop
+      44: heavyCottonPaper
+      45: veryHeavyPaper
+      46: heavyGloss
+      47: rfidLabels
+      48: businessCard
+  - name: deviceAlertSeverity
+    oid: 1.3.6.1.4.1.641.6.5.1.1.4
+    type: gauge
+    help: The severity of this alert - 1.3.6.1.4.1.641.6.5.1.1.4
+    indexes:
+    - labelname: deviceIndex
+      type: gauge
+    - labelname: deviceAlertIndex
+      type: gauge
+    enum_values:
+      1: unknown
+      2: other
+      3: informational
+      4: warning
+      5: critical
+      6: serviceRequired
+  - name: deviceAlertCode
+    oid: 1.3.6.1.4.1.641.6.5.1.1.5
+    type: gauge
+    help: An alert code to indicate what type of alert condition this row refers to
+      - 1.3.6.1.4.1.641.6.5.1.1.5
+    indexes:
+    - labelname: deviceIndex
+      type: gauge
+    - labelname: deviceAlertIndex
+      type: gauge
+    enum_values:
+      1: unknown
+      2: other
+      3: coverOpen
+      4: coverClosed
+      5: interlockOpen
+      6: interlockClosed
+      7: doorOpen
+      8: doorClosed
+      9: calibrating
+      10: alignmentFailed
+      11: warrantyOverrideRequired
+      12: printHeadCarrierPathObstructed
+      13: heldJobsMayNotBeRestored
+      14: busy
+      15: waiting
+      100: subunitErrorOther
+      101: subunitLifeAlmostOver
+      102: subunitLifeOver
+      103: subunitJammed
+      104: subunitUnderTemperature
+      105: subunitOverTemperature
+      106: subunitInsufficientMemory
+      107: subunitMemoryFull
+      108: subunitNVFailure
+      109: subunitDisabled
+      110: subunitCommunicationError
+      200: supplyErrorOther
+      201: supplyOk
+      202: supplyEarlyWarning
+      203: supplyNearFull
+      205: supplyFull
+      206: supplyNearLow
+      207: supplyLow
+      208: supplyNearEmpty
+      209: supplyEmpty
+      210: supplyLifeAlmostOver
+      211: supplyLifeOver
+      212: supplyNearReplace
+      213: supplyReplace
+      214: supplyMissing
+      215: supplyInvalid
+      216: supplyDefective
+      217: supplyImproperInstall
+      218: supplyUnsupported
+      219: supplyUncalibrated
+      300: inputMediaErrorOther
+      301: inputMediaTrayMissing
+      302: inputMediaSupplyLow
+      303: inputMediaSupplyEmpty
+      304: inputMediaChangeRequest
+      305: inputMediaLoadRequest
+      400: outputMediaErrorOther
+      401: outputMediaTrayMissing
+      402: outputMediaNearFull
+      403: outputMediaFull
+      404: outputMediaEmptyRequest
+      500: mediaPathErrorOther
+      501: mediaPathPaperJam
+      600: scannerErrorOther
+      601: scannerLampWarming
+      602: scannerLampLifeWarning
+      603: scannerLampError
+      604: scannerADFJam
+      605: scannerStalled
+      606: scannerLocked
+      607: scannerDisabled
+      700: faxErrorOther
+      701: faxStorageNearFull
+      702: faxStorageFull
+      703: faxStorageSendNearFull
+      704: faxStorageSendFull
+      705: faxStorageReceiveNearFull
+      706: faxStorageReceiveFull
+      707: faxPhoneLineDisconnected
+      708: faxDisabled
+      709: faxConfigurationError
+      800: interpreterErrorOther
+      801: interpreterInsufficientMemory
+      802: interpreterOutOfMemory
+      803: interpreterComplexPage
+      804: interpreterJobHardwareMismatch
+      805: interpreterPrintDataExceedsMediaSize
+      900: emailErrorOther
+      901: emailConfigurationError
+      1000: storageErrorOther
+      1001: storageUnformatted
+      1002: storageFull
+      20000: neverError
+  - name: deviceAlertDescription
+    oid: 1.3.6.1.4.1.641.6.5.1.1.6
+    type: DisplayString
+    help: A description of the alert condition - 1.3.6.1.4.1.641.6.5.1.1.6
+    indexes:
+    - labelname: deviceIndex
+      type: gauge
+    - labelname: deviceAlertIndex
+      type: gauge
diff --git a/roles/prometheus/templates/prometheus/alert.rules.yml.j2 b/roles/prometheus/templates/prometheus/alert.rules.yml.j2
index 3ed69bf7..cc1f7a96 100644
--- a/roles/prometheus/templates/prometheus/alert.rules.yml.j2
+++ b/roles/prometheus/templates/prometheus/alert.rules.yml.j2
@@ -354,6 +354,92 @@ groups:
         Le switch de réinitialisation n'est pas à l'état d'origine,
         l'authentification est bypassée sur {{ $labels.instance }}
 
+  ###########
+  # Printer #
+  ###########
+
+  - alert: PrinterWarning
+    expr: deviceAlertDescription >= 1
+    for: 3m
+    labels:
+      severity: warning
+    annotations:
+      summary: >-
+        L'imprimante {{ $labels.instance }} a un message d'erreur : {{ $labels.deviceAlertDescription }}
+
+  - alert: PrinterDoorOpen
+    expr: prtCoverStatus{prtCoverStatus="coverClosed"} != 1
+    for: 3m
+    labels:
+      severity: warning
+    annotations:
+      summary: >-
+        La porte n°{{ $labels.prtCoverIndex }} est ouverte sur {{ $labels.instance }}
+
+  - alert: PrinterTonerLow
+    expr: prtMarkerSuppliesLevel < 1000
+    for: 3m
+    labels:
+      severity: warning
+    annotations:
+      summary: >-
+        Le niveau de toner n°{{ $labels.prtMarkerSuppliesIndex }} de {{ $labels.instance }} est bas ({{ $value }} feuilles restantes)
+
+  - alert: PrinterTonerMissing
+    expr: prtMarkerSuppliesLevel == 0
+    for: 3m
+    labels:
+      severity: critical
+    annotations:
+      summary: >-
+        Le toner n°{{ $labels.prtMarkerSuppliesIndex }} de {{ $labels.instance }} est vide ou inexistant
+
+  - alert: PrinterPaperJam
+    expr: prtgenStatusPaperJam != 1
+    for: 3m
+    labels:
+      severity: critical
+    annotations:
+      summary: >-
+        Bourrage papier dans l'imprimante {{ $labels.instance }}
+
+  - alert: PrinterPaperEmpty
+    expr: prtgenStatusInputEmpty != 1
+    for: 3m
+    labels:
+      severity: critical
+    annotations:
+      summary: >-
+        Il n'y a plus de papier dans l'imprimante {{ $labels.instance }}
+
+  - alert: PrinterCoverOpen
+    expr: prtgenStatusCoverOpen != 1
+    for: 3m
+    labels:
+      severity: warning
+    annotations:
+      summary: >-
+        Le couvercle de l'imprimante {{ $labels.instance }} est ouvert
+
+  - alert: PrinterPaperTonerError
+    expr: prtgenStatusTonerError != 1
+    for: 3m
+    labels:
+      severity: critical
+    annotations:
+      summary: >-
+        Il y a un problème de toner dans l'imprimante {{ $labels.instance }}
+
+  - alert: PrinterSystemError
+    expr: prtgenStatusSrvcReqd != 1
+    for: 3m
+    labels:
+      severity: critical
+    annotations:
+      summary: >-
+        Une maintenance de l'imprimante {{ $labels.instance }} est requise
+
+
   #########
   # Other #
   #########