Icinga2 rest api set downtime to host with all services

hi everyone,

thanks for maintaining this community, I have learned a lot so far but now I need to ask a question.

We are using Icinga2 - the latest version and I would like to schedule a downtime for a host before we update and reboot the server - all via ansible.

it’s already working for normal hostnames:

# variables:
icinga_api_user: 'user'
icinga_api_pass: 'password'
icinga_host: 'https://mon.domain.de'
icinga_api_port: '5665'
icinga_dt_url: '/v1/actions/schedule-downtime?'
icinga_type: "Host"
icinga_author: 'ansible_automation'
icinga_comment: 'scheduled downtime for updates'
icinga_duration: 3600

# task
- name: set downtime to host
  delegate_to: localhost
  become: false
  uri:
    url: "{{ icinga_host }}:{{ icinga_api_port }}{{ icinga_dt_url }}type={{ icinga_type }}&{{ icinga_type|lower }}={{ item }}"
    user: "{{ icinga_api_user }}"
    password: "{{ icinga_api_pass }}"
    validate_certs: false
    method: POST
    body_format: json
    headers:
      Accept: "application/json"
    status_code: 200
    body: '{ "author": "{{ icinga_author }}", "comment": "{{ icinga_comment }}",
          "all_services": true, "start_time": {{ ansible_date_time.epoch }},
          "end_time": "{{ ansible_date_time.epoch | int + icinga_duration | int }}", "duration": {{ icinga_duration }}, "fixed": false }'
  with_items: "{{ inventory_hostname }}"
  when: icinga_type == 'Host'

# works for hostname:
project-dev-testhost01 # its a centos7 host

# doesn't work for:
PROJECT-TEST001.project-intern.de # its a win10 test system

#error:
TASK [set downtime to host] *******************************************************************
[WARNING]: Module did not set no_log for password
failed: [PROJECT-TEST001.project-intern.de -> localhost] (item=PROJECT-TEST001.project-intern.de) => {"ansible_loop_var": "item", "changed": false, "content_length": "214", "content_type": "application/json", "elapsed": 5, "item": "PROJECT-TEST001.project-intern.de", "json": {"error": 400, "status": "Invalid request body: Error: [json.exception.parse_error.101] parse error at line 1, column 130: syntax error while parsing object key - unexpected number literal; expected string literal\n"}, "msg": "Status code was 400 and not [200]: HTTP Error 400: Bad Request", "redirected": false, "server": "Icinga/2.13.2-1", "status": 400, "URL": "https://mon.domain.de:5665/v1/actions/schedule-downtime?type=Host&host=PROJECT-TEST001.project-intern.de"}

The Error code is from the Icinga Rest API but I don’t get it - the same code with another hostname works. here are the host definitions:

# this one works
object Host "project-dev-testhost01" {
  import "generic-host-linux"
  import "generic-host-project"

  address = "172.23.10.123"
  vars.ignore_services = [ "swap", ]
  vars.notifications = [ "voice", ]
}

#this one doesn't work
object Host "PROJECT-TEST001.project-intern.de" {
  import "generic-host-windows"
  import "generic-host-project"

  address = "172.23.70.32"
  display_name = "project-test01"
}

Give as much information as you can, e.g.

  • Version used (icinga2 --version)
[root@mon]# icinga2 --version
icinga2 - The Icinga 2 network monitoring daemon (version: 2.13.2-1)

Copyright (c) 2012-2023 Icinga GmbH (https://icinga.com/)
License GPLv2+: GNU GPL version 2 or later <https://gnu.org/licenses/gpl2.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

System information:
  Platform: CentOS Linux
  Platform version: 8
  Kernel: Linux
  Kernel version: 4.18.0-348.7.1.el8_5.x86_64
  Architecture: x86_64

Build information:
  Compiler: GNU 8.4.1
  Build host: runner-hh8q3bz2-project-322-concurrent-0
  OpenSSL version: OpenSSL 1.1.1k  FIPS 25 Mar 2021

Application information:

General paths:
  Config directory: /etc/icinga2
  Data directory: /var/lib/icinga2
  Log directory: /var/log/icinga2
  Cache directory: /var/cache/icinga2
  Spool directory: /var/spool/icinga2
  Run directory: /run/icinga2

Old paths (deprecated):
  Installation root: /usr
  Sysconf directory: /etc
  Run directory (base): /run
  Local state directory: /var

Internal paths:
  Package data directory: /usr/share/icinga2
  State path: /var/lib/icinga2/icinga2.state
  Modified attributes path: /var/lib/icinga2/modified-attributes.conf
  Objects path: /var/cache/icinga2/icinga2.debug
  Vars path: /var/cache/icinga2/icinga2.vars
  PID path: /run/icinga2/icinga2.pid
  • Enabled features (icinga2 feature list)
[root@mon]# icinga2 feature list
Disabled features: command compatlog debuglog elasticsearch gelf graphite icingadb influxdb livestatus opentsdb perfdata statusdata syslog
Enabled features: api checker ido-mysql influxdb2 mainlog notification
  • Icinga Web 2 version and modules (System - About)
Icinga Web 2 Version
2.9.5
Git commit
053971c99dc1a4510beb64a888ea695cc14032dc
PHP Version
7.4.33
Git commit date
2021-11-18
Copyright
© 2013-2023 Icinga GmbH
 
   
Loaded Libraries
Name	Version
icinga/icinga-php-library	0.7.0
icinga/icinga-php-thirdparty	0.10.0
Loaded Modules
Name	Version
grafana	1.4.2
monitoring	2.9.5
  • Config validation (icinga2 daemon -C)
[root@mon]# icinga2 daemon -C
[2023-02-21 14:09:23 +0100] information/cli: Icinga application loader (version: 2.13.2-1)
[2023-02-21 14:09:23 +0100] information/cli: Loading configuration file(s).
[2023-02-21 14:09:23 +0100] information/ConfigItem: Committing config item(s).
[2023-02-21 14:09:23 +0100] information/ApiListener: My API identity: mon.oneserv.de
[2023-02-21 14:09:25 +0100] warning/ApplyRule: Apply rule 'voice-service-group' (in /etc/icinga2/zones.d/master/notifications.conf: 131:1-131:51) for type 'Notification' does not match anywhere!
[2023-02-21 14:09:25 +0100] warning/ApplyRule: Apply rule 'apc_smartconnect' (in /etc/icinga2/zones.d/global-templates/services.conf: 33:1-33:32) for type 'Service' does not match anywhere!
[2023-02-21 14:09:25 +0100] warning/ApplyRule: Apply rule 'fping6' (in /etc/icinga2/zones.d/global-templates/services.conf: 240:1-240:22) for type 'Service' does not match anywhere!
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 NotificationComponent.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 IdoMysqlConnection.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 CheckerComponent.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 6 Users.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 UserGroup.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 2 TimePeriods.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 2390 Services.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 250 Zones.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 6 NotificationCommands.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 11 HostGroups.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 4646 Notifications.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 IcingaApplication.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 250 Hosts.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 249 Endpoints.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 33 Comments.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 FileLogger.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 2 ApiUsers.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 Influxdb2Writer.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 265 CheckCommands.
[2023-02-21 14:09:25 +0100] information/ConfigItem: Instantiated 1 ApiListener.
[2023-02-21 14:09:25 +0100] information/ScriptGlobal: Dumping variables to file '/var/cache/icinga2/icinga2.vars'
[2023-02-21 14:09:25 +0100] information/cli: Finished validating the configuration file(s).
  • If you run multiple Icinga 2 instances, the zones.conf file (or icinga2 object list --type Endpoint and icinga2 object list --type Zone) from all affected nodes
    • we run multiple zones but only one master, so that shouldn’t matter

Thank you all for your help!
cheers Ringo

Welcome to the community.

Run the playbook with -vvv and compare the JSON request bodies.

Also the maybe this Role helps as I can attest to it working well: lfops/Windows.yml at 019fd52d63818a227770e6ff42f035e8c87c828a · Linuxfabrik/lfops · GitHub

wild guess: URL encode the hostname in the url

Or try only calling /actions/schedule-downtime in the url and put a filter in the body
(copy&paste from on of our roles)

{
  "pretty": true,
  "type": "Host",
  "filter": "match(\"*{{ var_role_vm_hostname_full }}*\", host.name)",
  "all_services": true,
  "author": "some-user",
  "comment": "some text here",
  "fixed": true,
  "start_time": "{{ lookup('ansible.builtin.pipe', 'date +%s') }}",
  "end_time": "{{ (var_role_stop_date | to_datetime).strftime('%s') }}" # Convert date to epoch
}

(ansible_date_time is only available when gather_facts: true is set, that’s why we use something else)

thanks guys! in the end i have tested a little bit but couldn’t get it to work, so I have copied Dominiks code and changed it for our use case … baam it works! still not sure what my problem was in my code, that looks more neat anyways :slight_smile: cheers Ringo

    body:
      {
        "pretty": true,
        "type": "Host",
        "filter": "match(\"*{{ item }}*\", host.name)",
        "all_services": true,
        "author": "{{ icinga_author }}",
        "comment": "{{ icinga_comment }}",
        "fixed": false,
        "start_time": "{{ lookup('ansible.builtin.pipe', 'date +%s') }}",
        "end_time": "{{ lookup('ansible.builtin.pipe', 'date +%s') | int + icinga_duration | int }}",
        "duration": "{{ icinga_duration }}"
      }