Trying to get the address of the parent of a host

Hi.

I’m using Icinga 2.13.6 in a distributed environment (currently Master, two Satellites, and four Agents per Satellite). The Master is in a data centre (public IP address) but the Satellites and Agents are behind two different NAT routers, therefore the Agents can connect to their local Satellite on the local network, and both Agents and Satellites can route out to the Master, but the Master cannot connect in to the Satellites.

I’m setting up a “Network Connectivity” service check, which verifies connectivity from the Agents to the Satellites and from the Satellites to the Master. I’m using a ping4 Service Check for this, which runs on every Agent and Satellite, with the parameter “ping_address” set to the Satellite’s resolvable name in the case of an Agent, and the Master’s resolvable name in the case of a Satellite.

So far, so good, however for scalability I would like the Service Check definition to be able to work out the parent’s resolvable name automatically. The parent is a property of a Zone, and I can get the name of the Zone in which a machine lives using "get_object(“Zone”,zone), but I’m stuck on trying to get the resolvable name of the Host in that Zone.

So far, I’ve tried:
get_object(“Zone”,zone).address
get_host(get_object(“Zone”,zone)).address
get_host(string(get_object(“Zone”,zone))).address

All of these end up with ‘null’ as the ping_address when I do “icinga2 object list --name MyNewService”.

If I just use get_object(“Zone”,zone) then the Service Check in IcingaWeb2 tells me that my ping_address is an Object of type ‘Zone’, which is fair enough.

Anyone got any suggestions on how to find the address of the Host in the Parent Zone?

Thanks,

Antony.

Hi.

Update in the meantime:

I’ve tried:

get_host(get_object(“Zone”,zone).parent).address
string(get_host(get_object(“Zone”,zone).parent).address)

Both of these produce the hostname I actually want, however it doesn’t work -
the Service Check output simply says:

check_ping: Invalid hostname/address -

The Custom Variables section of the Service Check screen in IcingaWeb2 shows
the correct value for ping_address.

So, I’m obviously close, but not quite close enough.

Anyone have any ideas?

Antony.

So:

get_host(get_object(“Zone”,zone).parent).address

produces the hostname I actually want, however it doesn’t work - the Service
Check output simply says:

check_ping: Invalid hostname/address -

The Custom Variables section of the Service Check screen in IcingaWeb2 shows
the correct DNS resolvable name for ping_address.

If instead I set the ping address to “host.address” (ie: the address of this
machine itself, but the same object type as the parent’s address above) then
everything works. In both cases the result is a DNS-resolvable host name for
the machine performing the Service Check.

What’s the fundamental difference between:

ping_address = host.address

and

ping_address = get_host(get_object(“Zone”,zone).parent).address

which means that the first one works and the second one doesn’t?

Anyone got any debugging hints?

Antony.

Why don’t you simply use cluster-zone to verify connectivity implicitly?

Yes, I know that’s an option; I’ve used it in the past and I like it, however
I’d still like to know what I’m doing wrong when:

ping_address = host.address

works, but

ping_address = get_host(get_object(“Zone”,zone).parent).address

doesn’t, and yet the string out from that second command is the exact hostname
I want, and putting that in as:

ping_address = “ser.ver.add.ress”

works fine.

What is wrong with get_host(get_object(“Zone”,zone).parent).address which
means it doesn’t get accepted as the ping_address parameter?

Antony.

returns the name of the parent zone but not the host name. You need to evaluate endpoints instead.

“You need to evaluate endpoints instead.”

So, are you suggesting that I should be defining a host= value for all of my
endpoints?

Distributed Monitoring - Icinga 2 says in
several places “Choose one connection direction” and my understanding is that
this is achieved by ensuring that between the child and the parent, only one
of those Endpoints contains a Host definition.

If I use “icinga2 object list --type Endpoint”, nearly all entries come back
with host=“”

Thanks for the follow-up.

Antony.

no, it’s already defined:

get_object(“Zone”,zone).endpoints

“no, it’s already defined:”
get_object(“Zone”,zone).endpoints

Okay, so that tells me the Endpoints of the Zone of this Node - that comes
back as an array, the single element of which is the name of this Node. I
don’t really see how that helps?

get_object(“Zone”,zone).parent

tells me the parent of the Zone of this Node, which is closer to what I want.

get_object(“Zone”,zone).parent.endpoints

Fails with the error “Invalid field access (for value of type ‘String’):
‘endpoints’” which means to me that get_object(“Zone”,zone is being returned
as a String?

So, if you say I should be working with Endpoints, how do I get the Endpoints
of the parent Zone of the Zone in which this Node is?

Thanks,

Antony.

I thought I’d got it:

get_host(get_object(“Zone”,get_object(“Zone”,zone).parent).endpoints[0]).address

It shows exactly what I want in the output of “icinga2 object list --name
MyNewService”, and it also shows exactly the right hostname for “ping_address”
in the IcingaWeb2 Custom Variables section.

But… the service check fails with:

check_ping: Invalid hostname/address -

which I’ve seen before, when both the object description and the ping_address
look completely correct to me.

Maybe I need to re-phrase my question, now that I have at least two different
ways of getting the hostname I want, but neither of them work with the ping
check:

“What type of object do I need to specify for ping_address in order for it to
accept what reads to me as the completely correct hostname, and how would I
convert what reads as the right name into such an object?”

Antony.

What does icinga2 object list of your service object looks like after config validation or reload?

have you checked the data type of those three?
I could imagine, that host.address resolves “magically” to something directly usable.
maybe somthing like this comes into play here

a = "test"
 typeof(a) == String
true
typeof(a) == "String"
false
typeof(a).name == "String"
true

Cutting out verbosity:

icinga2 object list --name ‘AgentNode3!MyNewService’

Object ‘AgentNode3!MyNewService’ of type ‘Service’:

  • check_command = “ping4”
  • name = “MyNewService”
  • vars
    • ping_address = “Par.ent.DNS.entry”
  • zone = “AgentNode3”

I’ve also established the following:

vars.myparent = “Par.ent.DNS.entry”
vars.ping_address = vars.myparent

does work.

vars.myparent =
vars.ping_address = vars.myparent

does not work.

In both cases, the object list output shows exactly the same.

Antony.

have you checked the data type of those three?
I could imagine, that host.address resolves "magically" to something
directly usable. maybe somthing like this comes into play here

a = "test"
typeof(a) == String
true
typeof(a) == "String"
false
typeof(a).name == "String"
true

No; I’ve not tried that. Where would I run such a test from? Can I use for
example icingacli to get into a command line where I can get the output of
this sort of thing?

Antony.

Yes, exactly:
https://icinga.com/docs/icinga-2/latest/doc/11-cli-commands/#cli-command-console

Hm, thanks, but I think I need a bit more guidance than is shown in the
documentation.

icinga2 console

Icinga 2 (version: r2.13.6-1)
Type $help to view available commands.
<1> => var x=get_host(“Agent3”)
null
<2> => x.address
null
<3> => var x=get_host(“Agent3.domain.local”)
null
<4> => x.address
null

That was trying to get some very basic information about a Host whose name is
Agent3 and whose FQDN is Agent3.domain.local

As you can see, I failed even to get something simple.

Any pointer to more comprehensive documentation and/or examples would be
welcome :slight_smile:

Antony.

So, I’ve worked out that “icinga2 console” doesn’t actually let you interact
with anything to do with the machine’s Icinga2 configuration :frowning:

You need to find out what password got assigned and stored in
/etc/icinga2/conf.d/api-users.conf and then use this, along with --connect, in
order to get a console which knows about the configuration on the machine.

Now I get:

Icinga 2 (version: r2.13.6-1)
Type $help to view available commands.
<1> => var x=get_host(“Agent3”)
null
<2> => x.address
“Agent3.domain.local”

Much more encouraging.

Therefore, coming back to log1c’s question “have you checked the data type of
those three?”

=> a=“Parent.domain.local”
null
=> typeof(a)==String
true
=> typeof(a)==“String”
false
=> typeof(a).name==“String”
true

=> a=get_host(“Agent3”).address
null
=> typeof(a)==String
true
=> typeof(a)==“String”
false
=> typeof(a).name==“String”
true

=> a=get_host(get_object(“Zone”,get_host(“Agent3”).zone).parent).address
null
=> typeof(a)==String
true
=> typeof(a)==“String”
false
=> typeof(a).name==“String”
true

So, I cannot identify any difference between:

ping_address = “ser.ver.add.ress”

which works, and:

ping_address = get_host(get_object(“Zone”,zone).parent).address

which fails with “check_ping: Invalid hostname/address -”

How to debug further?

Antony.