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 # #########