logo

NJP

Why Doesn't This Work? Or, A Puzzle Explained...

Import · Oct 21, 2011 · article

[imageI'm told that just a few weeks ago, our correspondent at right looked like the young man he actually is. Then he tried to write what he thought was a simple little script on his company's ServiceNow instance. After a few days that involved facepalms, banging his head against the wall, banging other people's heads against the wall, screaming, and some possibly licit intoxicants … he looked like this.

He should have contacted me earlier. He was doing almost everything correctly. All he was missing was one key piece of understanding, and the answer would have been obvious.

He needed to understand composite tables.First, let's look at his code that didn't work. He was trying to write a function which, given the IP address of a computer, would return its name. His function worked fine for workstations and laptops, but not for servers. Here's what he had:

gs.log(findName('10.0.10.69'));function findName(ip) { var gr = new GlideRecord('cmdb_ci_ip_address'); gr.addQuery('ip_address', ip); gr.query(); if (!gr.next()) return null; var nic_id = '' + gr.nic; gr = new GlideRecord('cmdb_ci_network_adapter'); if (!gr.get(nic_id)) return null; var computer_id = '' + gr.cmdb_ci; gr = new GlideRecord('cmdb_ci_computer'); if (!gr.get(computer_id)) return null; var kind = '' + gr.sys_class_name; if (kind == 'cmdb_ci_computer') return '' + gr.name; return '' + gr.host_name;

}

Most of this is quite straightforward code that navigates through the CMDB database. First it finds the IP address table record with the desired IP address, then it uses that record's reference (nic) to locate the NIC (network adapter) record that is provisioned for that IP address. Once it has the NIC, it uses that record's CI reference (cmdb_ci) to locate the computer that the NIC is installed in. If any of this logic fails, it simply returns a null. So far, this is all just fine.

Right near the end is where our prematurely old friend goes horribly wrong. His code looks at the class name (sys_class_name) of the computer record to see if it's a plain old computer (which would mean it was a workstation or laptop) or something else (which would mean it was some kind of server). If it's a computer, it returns the contents of the name field — this is the part the works just fine. But if it's a server, it tries to return the host name (a field that only servers have). This fails miserably, returning an 'undefined'. Our aged friend can go look at the record for the server with that IP address, and the host name is staring him right in the face. It's there, dang it! What's up with the undefined?

The problem is that his code queried cmdb_ci_computer, not the actual server table. So what? Well, that's where you really need to understand composite tables...

When you query the cmdb_ci_computer table, under the covers the ServiceNow instance is actually joining three tables together to produce the results you find in your GlideRecord instance:

View original source

https://www.servicenow.com/community/in-other-news/why-doesn-t-this-work-or-a-puzzle-explained/ba-p/2282445