DX Infrastructure Manager

Expand all | Collapse all

lua script - bad argument #1 to 'pairs' (table expected, got nil)

Jump to Best Answer
  • 1.  lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-27-2019 06:39 AM

    Hi all,

     

    I have a lua script that pulls back hubs, robots, probes and the state of the probe.

    This has been working for a number of years and it has recently started failing with the error message

    "Error in line 78: bad argument #1 to 'pairs' (table expected, got nil)"

     

    I am unsure what could be causing this and also how to add error handling to deal with nil.

     

    Is anybody able to assist please or point me in the right direction ?

     

    When I uncomment line 87 , I do receive an output along with the error. I am wondering if it is failing on a certain device.. ?

    Also, this script can be copied and pasted to another system and will run without any issues.

     

    EDIT:

    I decided to change line 76 from "if r_entry.status == 0 then" to "if r_entry.status == nil then" and I now get an output to the database, ie; the script has ran successfully, some robots are missing.

    I just need to work out which ones are missing and why.

     

    -- This script polls the primary hub for a list of hubs, and polls each hub for its robot and probe information.
    -- It then logs the robot and probe lists to tables in the NIS database.


    ---------- VARIABLES ----------

    -- Domain to use for fetching hubs/robots/probes
    NIMSOFT_DOMAIN = "UIM"

    -- DB tables used for storing results
    ROBOT_INVENTORY_TABLE = "Audit_RobotInventory"
    PROBE_INVENTORY_TABLE = "Audit_ProbeInventory"

    -- use this format to connect to the NIS DB - that same DB that data_engine connects to
    DB_CONNECTION_STRING = "provider=nis;database=nis;driver=none"

    -- use this format to specify some other (external) database if desired
    --DB_CONNECTION_STRING = "Provider=SQLOLEDB;Data Source=DBSERVER;Initial Catalog=DBNAME;User ID=USER;Password=PASSWORD"

    -------------------------------

     

    -- initially empty list of hubs (table meant to hold the full list of robots and probes)
    hub_robot_probes = {}

    -- get list of all hubs using the "gethubs" callback command
    hubs = nimbus.request("hub", "gethubs")

    if hubs == nil then
    return
    end

    -- argument for the "getrobots" callback command on the hub probe
    getrobots_args = pds.create()
    pds.putString(getrobots_args, "name", "") -- all robots
    pds.putInt(getrobots_args, "detail", 1) -- request detailed (probe) info about each = 1

    --validate hubs.hublist
    if hubs.hublist == nil then
    return
    end

    -- iterate through all hubs
    for hub_index, hub_entry in pairs (hubs.hublist) do

    -- make sure we're only checking our domain (avoid visible test/dev domains)
    if hub_entry.domain == NIMSOFT_DOMAIN then

    -- initialize empty robot-list for this hub
    hub_robot_probes[hub_entry.name] = { }
    -- request robot/probe list using the hub's address, the command name, and the constructed argument
    local robots, hub_stat = nimbus.request(hub_entry.addr, "getrobots", getrobots_args)
    -- if request was successful
    if hub_stat == 0 then

    -- iterate through robot list
    for r_row,r_entry in pairs (robots.robotlist) do
    -- add entry into our table for this robot and its status
    hub_robot_probes[hub_entry.name][r_entry.name] = { }
    hub_robot_probes[hub_entry.name][r_entry.name]["status"] = r_entry.status
    hub_robot_probes[hub_entry.name][r_entry.name]["created"] = r_entry.created
    hub_robot_probes[hub_entry.name][r_entry.name]["ip"] = r_entry.ip
    hub_robot_probes[hub_entry.name][r_entry.name]["addr"] = r_entry.addr
    hub_robot_probes[hub_entry.name][r_entry.name]["version"] = r_entry.version
    hub_robot_probes[hub_entry.name][r_entry.name]["os_user1"] = r_entry.os_user1
    hub_robot_probes[hub_entry.name][r_entry.name]["os_user2"] = r_entry.os_user2
    hub_robot_probes[hub_entry.name][r_entry.name]["os_major"] = r_entry.os_major
    hub_robot_probes[hub_entry.name][r_entry.name]["os_minor"] = r_entry.os_minor
    hub_robot_probes[hub_entry.name][r_entry.name]["os_description"] = r_entry.os_description
    hub_robot_probes[hub_entry.name][r_entry.name]["maint_until"] = r_entry.maint_until
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"] = { }

    -- only pay attention to robots that currently have a normal status
    -- (other robots will not have a probe list anyway)
    if r_entry.status == 0 then
    -- iterate through probe list
    for p_row,p_entry in pairs (r_entry.probelist) do
    -- add entry into our table for this probe and its status
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name] = { }
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["active"] = p_entry.active
    if (hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] == nil) then
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] = "-"
    end
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] = p_entry.pkg_version
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["last_started"] = p_entry.last_started
    -- print(r_entry.addr .. "/" .. p_entry.name .. ": " .. p_entry.active)
    end
    end
    end
    end
    end
    end

    -- de-construct this PDS request (argument), as it requires clean-up
    pds.delete(getrobots_args)


    -- prepare to build query text for inserting of records into the database
    robot_insert_queries = { }
    probe_insert_queries = { }

    robot_insert_query_original = "INSERT INTO " .. ROBOT_INVENTORY_TABLE .. " (Hub, Robot, Created, RobotStatus, IPAddress, RobotAddress, RobotVersion, UserTag1, UserTag2, OSMajor, OSMinor, OSDescription, MaintUntil) VALUES "
    robot_insert_query = robot_insert_query_original


    probe_insert_query_original = "INSERT INTO " .. PROBE_INVENTORY_TABLE .. " (Hub, Robot, Probe, ProbeActiveState, ProbeVersion, ProbeStarted) VALUES "
    probe_insert_query = probe_insert_query_original

    -- iterate through our full (now-populated) list (hubs)
    for h, rl in pairs(hub_robot_probes) do
    -- print(h)
    -- iterate through robots
    for r, rinfo in pairs(rl) do
    --print(r)
    -- determine if created value is valid or not, and parse it if so
    local robot_created = "NULL"
    if (rinfo.created ~= nil and rinfo.created > 0) then
    robot_created = "'" .. timestamp.format(rinfo.created, "%c") .. "'"
    end

    -- If robot is in Maintenance Mode, then format the date and add quotes
    local maint_until = "NULL"
    if (rinfo.status == 4) then
    maint_until = "'" .. timestamp.format(rinfo.maint_until, "%c") .. "'"
    end

    -- build query for insertion of robot records
    robot_insert_query = robot_insert_query .. "('" .. h .. "','" .. r .. "'," .. robot_created .. "," .. rinfo.status .. ",'" .. rinfo.ip .. "','" .. rinfo.addr .. "','" .. rinfo.version .. "','" .. rinfo.os_user1 .. "','" .. rinfo.os_user2 .. "','" .. rinfo.os_major .. "','" .. rinfo.os_minor .. "','" .. rinfo.os_description .. "'," .. maint_until ..")"
    -- print(r .. ": " .. rinfo.status)
    table.insert (robot_insert_queries, robot_insert_query)
    robot_insert_query = robot_insert_query_original

    -- Check if this robot was on-line/OK
    if rinfo.status == 0 then

    -- iterate through probes
    for probe,pinfo in pairs (rinfo.probes) do

    -- determine if last started value is valid or not, and parse it if so
    local probe_started = "NULL"
    if (pinfo.last_started ~= nil and pinfo.last_started > 0) then
    probe_started = "'" .. timestamp.format(pinfo.last_started, "%c") .. "'"
    end
    --If Package Version comes back empty, make it a dash
    if (pinfo.pkg_version == nil) then
    pkg_version = "'-'"
    else
    pkg_version = pinfo.pkg_version
    end
    --print(" " .. probe .. ": " .. pinfo)

    -- build query for insertion of probe records
    probe_insert_query = probe_insert_query .. "('" .. h .. "','" .. r .. "','" .. probe .. "'," .. pinfo.active .. ",'" .. pkg_version .. "'," .. probe_started .. ")"
    -- print(" " .. probe .. ": " .. pinfo)

    -- add constructed query to list of queries
    table.insert (probe_insert_queries, probe_insert_query)

    -- reset the probe query so it can be build again for the next robot
    probe_insert_query = probe_insert_query_original
    end
    end
    end
    end

    -- open connection to NIS database
    db_stat = database.open(DB_CONNECTION_STRING)

    -- Create tables if they don't exist or just truncate them
    RobotTable = "IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '" .. ROBOT_INVENTORY_TABLE .. "') TRUNCATE TABLE " .. ROBOT_INVENTORY_TABLE .. " ELSE BEGIN CREATE TABLE " .. ROBOT_INVENTORY_TABLE .. " (Hub varchar(55), Robot varchar(55), Created datetime, RobotStatus int, IPAddress varchar(55), RobotAddress varchar(100), RobotVersion varchar(55), UserTag1 varchar(55), UserTag2 varchar(55), OSMajor varchar(55), OSMinor varchar(100), OSDescription varchar(100),MaintUntil datetime); END"
    ProbeTable = "IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '" .. PROBE_INVENTORY_TABLE .. "') TRUNCATE TABLE " .. PROBE_INVENTORY_TABLE .. " ELSE BEGIN CREATE TABLE " .. PROBE_INVENTORY_TABLE .. " (Hub varchar(55), Robot varchar(55), Probe varchar(55), ProbeActiveState int, ProbeVersion varchar(55), ProbeStarted datetime); END"
    rs = database.query(RobotTable)
    rs = database.query(ProbeTable)

    -- insert hub/robot list
    for i,q in pairs (robot_insert_queries) do
    -- insert robot/probe list
    rs = database.query(q)
    -- print (i .. ": " .. q)
    end

    -- iterate through robot/probe queries
    for i,q in pairs (probe_insert_queries) do
    -- insert robot/probe list
    rs = database.query(q)
    -- print (i .. ": " .. q)
    end

    -- close database connection
    database.close()



  • 2.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-27-2019 12:18 PM

    Perhaps it's legitimate for r_entry.probelist to be nil even though the status is zero?

     

    I'd suggest dumping that table if r_entry.probelist is nil to see what's there.

     

    If you don't have it:

     

    function tdump(t)
    local function dmp(t, l, k)
    if type(t) == "table" then
    print(string.format("%s%s:", string.rep(" ", l*2), tostring(k)))
    for k, v in pairs(t) do
    dmp(v, l+1, k)
    end
    else
    print(string.format("%s%s:%s", string.rep(" ", l*2), tostring(k), tostring(t)))
    end
    end
    dmp(t, 1, "root")
    end



  • 3.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-28-2019 10:30 AM

    Thanks for the reply, Garin.

    Can you let me know at which point your code should be entered please ?

     

    Thanks



  • 4.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-28-2019 11:06 AM

    The code I added is the "tdump()" function. 

     

    It's function is to recursively traverse a Lua table(and sub tables) and print the contents in a reasonable way.

     

    So at the global level of your script put the code I supplied. That would be somewhere before the line "---------- VARIABLES ----------" in your script for instance.

     

    Then wherever you want to see the contents of a table you can put "tdump(table name)"

     

    So I'd suggest that at line 78 you put the code:

     

    if ( r_entry.probelist == nil ) then -- catch questionable data situation

       tdump(r_entry) -- print enclosing table data

       print(nil .. nil) -- artificial error to stop code running

    end

     

    Then run it. You should then get some diagnostic information about the data causing your issue.

     

    Garin



  • 5.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-28-2019 11:38 AM

    Thanks for that Garin, really appreciated!

    It gives me a new result, but not 100% sure what it means. Could it be due to blank usertags and origis ?

    Or is it an error with something after "version" ?

     

    Output is below. I did remove a couple of entries from the output below, due it including server names etc, but they looked correct.

     

    I have also included the new version of the script below the output as a guide for line counts.

     

    ----------- Executing script at 3/28/2019 3:29:13 PM ----------

    root:
    last_config_reread:0
    os_user2:
    origin:
    os_major:UNIX
    ip:<removed>
    os_minor:Linux
    addr:<removed>
    status:2
    license:1
    last_inst_change:0
    created:1531243164
    offline:0
    os_user1:
    last_change:0
    lastupdate:1552313259
    autoremove:0
    os_description:Linux 3.10.0-862.11.6.el7.x86_64 #1 SMP Tue Aug 14 21:49:04 UTC 2018 x86_64
    flags:1
    metric_id:MB25ECBDC827B51D4EAFB33B4FD4DBDAC
    name:<removed>
    ssl_mode:0
    device_id:D35A92031AC67FF4BFE1C36178E968934
    heartbeat:900
    port:48000
    version:7.80 [Build 7.80.3132, Jun 1 2015]
    Error in line 78: attempt to concatenate a nil value

     

    --------------------------------------------

    --------------------------------------------

    --------------------------------------------

    --------------------------------------------

     

     

    -- This script polls the primary hub for a list of hubs, and polls each hub for its robot and probe information.
    -- It then logs the robot and probe lists to tables in the NIS database.


    ---------- VARIABLES ----------

    -- Domain to use for fetching hubs/robots/probes
    NIMSOFT_DOMAIN = "UIM"

    -- DB tables used for storing results
    ROBOT_INVENTORY_TABLE = "Audit_RobotInventory"
    PROBE_INVENTORY_TABLE = "Audit_ProbeInventory"

    -- use this format to connect to the NIS DB - that same DB that data_engine connects to
    DB_CONNECTION_STRING = "provider=nis;database=nis;driver=none"

    -- use this format to specify some other (external) database if desired
    --DB_CONNECTION_STRING = "Provider=SQLOLEDB;Data Source=DBSERVER;Initial Catalog=DBNAME;User ID=USER;Password=PASSWORD"

    function tdump(t)
    local function dmp(t, l, k)
    if type(t) == "table" then
    print(string.format("%s%s:", string.rep(" ", l*2), tostring(k)))
    for k, v in pairs(t) do
    dmp(v, l+1, k)
    end
    else
    print(string.format("%s%s:%s", string.rep(" ", l*2), tostring(k), tostring(t)))
    end
    end
    dmp(t, 1, "root")
    end

    -------------------------------

     

    -- initially empty list of hubs (table meant to hold the full list of robots and probes)
    hub_robot_probes = {}

    -- get list of all hubs using the "gethubs" callback command
    hubs = nimbus.request("hub", "gethubs")

    if hubs == nil then
    return
    end

    -- argument for the "getrobots" callback command on the hub probe
    getrobots_args = pds.create()
    pds.putString(getrobots_args, "name", "") -- all robots
    pds.putInt(getrobots_args, "detail", 1) -- request detailed (probe) info about each = 1

    --validate hubs.hublist
    if hubs.hublist == nil then
    return
    end

    -- iterate through all hubs
    for hub_index, hub_entry in pairs (hubs.hublist) do

    -- make sure we're only checking our domain (avoid visible test/dev domains)
    if hub_entry.domain == NIMSOFT_DOMAIN then

    -- initialize empty robot-list for this hub
    hub_robot_probes[hub_entry.name] = { }
    -- request robot/probe list using the hub's address, the command name, and the constructed argument
    local robots, hub_stat = nimbus.request(hub_entry.addr, "getrobots", getrobots_args)
    -- if request was successful
    if hub_stat == 0 then

    -- iterate through robot list

    for r_row,r_entry in pairs (robots.robotlist) do
    if ( r_entry.probelist == nil ) then -- catch questionable data situation

    tdump(r_entry) -- print enclosing table data

    print(nil .. nil) -- artificial error to stop code running

    end
    -- add entry into our table for this robot and its status
    hub_robot_probes[hub_entry.name][r_entry.name] = { }
    hub_robot_probes[hub_entry.name][r_entry.name]["status"] = r_entry.status
    hub_robot_probes[hub_entry.name][r_entry.name]["created"] = r_entry.created
    hub_robot_probes[hub_entry.name][r_entry.name]["ip"] = r_entry.ip
    hub_robot_probes[hub_entry.name][r_entry.name]["addr"] = r_entry.addr
    hub_robot_probes[hub_entry.name][r_entry.name]["version"] = r_entry.version
    hub_robot_probes[hub_entry.name][r_entry.name]["os_user1"] = r_entry.os_user1
    hub_robot_probes[hub_entry.name][r_entry.name]["os_user2"] = r_entry.os_user2
    hub_robot_probes[hub_entry.name][r_entry.name]["os_major"] = r_entry.os_major
    hub_robot_probes[hub_entry.name][r_entry.name]["os_minor"] = r_entry.os_minor
    hub_robot_probes[hub_entry.name][r_entry.name]["os_description"] = r_entry.os_description
    hub_robot_probes[hub_entry.name][r_entry.name]["maint_until"] = r_entry.maint_until
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"] = { }

    -- only pay attention to robots that currently have a normal status
    -- (other robots will not have a probe list anyway)
    if r_entry.status == 0 then
    -- iterate through probe list
    for p_row,p_entry in pairs (r_entry.probelist) do
    -- add entry into our table for this probe and its status
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name] = { }
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["active"] = p_entry.active
    if (hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] == nil) then
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] = "-"
    end
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] = p_entry.pkg_version
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["last_started"] = p_entry.last_started
    -- print(r_entry.addr .. "/" .. p_entry.name .. ": " .. p_entry.active)
    end
    end
    end
    end
    end
    end

    -- de-construct this PDS request (argument), as it requires clean-up
    pds.delete(getrobots_args)


    -- prepare to build query text for inserting of records into the database
    robot_insert_queries = { }
    probe_insert_queries = { }

    robot_insert_query_original = "INSERT INTO " .. ROBOT_INVENTORY_TABLE .. " (Hub, Robot, Created, RobotStatus, IPAddress, RobotAddress, RobotVersion, UserTag1, UserTag2, OSMajor, OSMinor, OSDescription, MaintUntil) VALUES "
    robot_insert_query = robot_insert_query_original


    probe_insert_query_original = "INSERT INTO " .. PROBE_INVENTORY_TABLE .. " (Hub, Robot, Probe, ProbeActiveState, ProbeVersion, ProbeStarted) VALUES "
    probe_insert_query = probe_insert_query_original

    -- iterate through our full (now-populated) list (hubs)
    for h, rl in pairs(hub_robot_probes) do
    -- print(h)
    -- iterate through robots
    for r, rinfo in pairs(rl) do
    --print(r)
    -- determine if created value is valid or not, and parse it if so
    local robot_created = "NULL"
    if (rinfo.created ~= nil and rinfo.created > 0) then
    robot_created = "'" .. timestamp.format(rinfo.created, "%c") .. "'"
    end

    -- If robot is in Maintenance Mode, then format the date and add quotes
    local maint_until = "NULL"
    if (rinfo.status == 4) then
    maint_until = "'" .. timestamp.format(rinfo.maint_until, "%c") .. "'"
    end

    -- build query for insertion of robot records
    robot_insert_query = robot_insert_query .. "('" .. h .. "','" .. r .. "'," .. robot_created .. "," .. rinfo.status .. ",'" .. rinfo.ip .. "','" .. rinfo.addr .. "','" .. rinfo.version .. "','" .. rinfo.os_user1 .. "','" .. rinfo.os_user2 .. "','" .. rinfo.os_major .. "','" .. rinfo.os_minor .. "','" .. rinfo.os_description .. "'," .. maint_until ..")"
    -- print(r .. ": " .. rinfo.status)
    table.insert (robot_insert_queries, robot_insert_query)
    robot_insert_query = robot_insert_query_original

    -- Check if this robot was on-line/OK
    if rinfo.status == 0 then

    -- iterate through probes
    for probe,pinfo in pairs (rinfo.probes) do

    -- determine if last started value is valid or not, and parse it if so
    local probe_started = "NULL"
    if (pinfo.last_started ~= nil and pinfo.last_started > 0) then
    probe_started = "'" .. timestamp.format(pinfo.last_started, "%c") .. "'"
    end
    --If Package Version comes back empty, make it a dash
    if (pinfo.pkg_version == nil) then
    pkg_version = "'-'"
    else
    pkg_version = pinfo.pkg_version
    end
    --print(" " .. probe .. ": " .. pinfo)

    -- build query for insertion of probe records
    probe_insert_query = probe_insert_query .. "('" .. h .. "','" .. r .. "','" .. probe .. "'," .. pinfo.active .. ",'" .. pkg_version .. "'," .. probe_started .. ")"
    -- print(" " .. probe .. ": " .. pinfo)

    -- add constructed query to list of queries
    table.insert (probe_insert_queries, probe_insert_query)

    -- reset the probe query so it can be build again for the next robot
    probe_insert_query = probe_insert_query_original
    end
    end
    end
    end

    -- open connection to NIS database
    db_stat = database.open(DB_CONNECTION_STRING)

    -- Create tables if they don't exist or just truncate them
    RobotTable = "IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '" .. ROBOT_INVENTORY_TABLE .. "') TRUNCATE TABLE " .. ROBOT_INVENTORY_TABLE .. " ELSE BEGIN CREATE TABLE " .. ROBOT_INVENTORY_TABLE .. " (Hub varchar(55), Robot varchar(55), Created datetime, RobotStatus int, IPAddress varchar(55), RobotAddress varchar(100), RobotVersion varchar(55), UserTag1 varchar(55), UserTag2 varchar(55), OSMajor varchar(55), OSMinor varchar(100), OSDescription varchar(100),MaintUntil datetime); END"
    ProbeTable = "IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '" .. PROBE_INVENTORY_TABLE .. "') TRUNCATE TABLE " .. PROBE_INVENTORY_TABLE .. " ELSE BEGIN CREATE TABLE " .. PROBE_INVENTORY_TABLE .. " (Hub varchar(55), Robot varchar(55), Probe varchar(55), ProbeActiveState int, ProbeVersion varchar(55), ProbeStarted datetime); END"
    rs = database.query(RobotTable)
    rs = database.query(ProbeTable)

    -- insert hub/robot list
    for i,q in pairs (robot_insert_queries) do
    -- insert robot/probe list
    rs = database.query(q)
    -- print (i .. ": " .. q)
    end

    -- iterate through robot/probe queries
    for i,q in pairs (probe_insert_queries) do
    -- insert robot/probe list
    rs = database.query(q)
    -- print (i .. ": " .. q)
    end

    -- close database connection
    database.close()



  • 6.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-28-2019 12:14 PM

    At the point of your failure, the r_entry variable contains the following:

     

    last_config_reread:0
    os_user2:
    origin:
    os_major:UNIX
    ip:<removed>
    os_minor:Linux
    addr:<removed>
    status:2
    license:1
    last_inst_change:0
    created:1531243164
    offline:0
    os_user1:
    last_change:0
    lastupdate:1552313259
    autoremove:0
    os_description:Linux 3.10.0-862.11.6.el7.x86_64 #1 SMP Tue Aug 14 21:49:04 UTC 2018 x86_64
    flags:1
    metric_id:MB25ECBDC827B51D4EAFB33B4FD4DBDAC
    name:<removed>
    ssl_mode:0
    device_id:D35A92031AC67FF4BFE1C36178E968934
    heartbeat:900
    port:48000
    version:7.80 [Build 7.80.3132, Jun 1 2015]

     

    You are trying to access "probelist" within this data but it appears that it does not exist - hence your "nil" error in the original post.

     

    So now you know that the bad data is that's causing your script to fail. 

     

    I'd take this and go look at this robot to see why it's not reporting having any probes installed. My understanding is that you should at least see controller in there but it's not.

     

    This is also a good lesson in interacting with UIM. Always code defensively - even when you think there should be no possible way something bad could happen, you should still check for it. It is likely to actually happen. 

     

    I don't know off hand but I wonder if "status:2" is an indication that the robot's not healthy. Maybe off line - the hub knows about it but is unable to query any information?

     

    -Garin

     



  • 7.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-28-2019 12:30 PM

    Thanks again.

    Yes, status 2 is robot inactive. The thing is, this script has worked for a number of years but was written when it may be have been robot/hub 7.80 or lower. The recently it started throwing this error.

     

    Maybe the way the status is presented has changed on the primary hub level. which was 7.92HF10.

    I can copy and paste this script and paste it into a nas on another UIM domain and runs flawlessly (domain variable needs changing of course).

     

    I have just removed the robot stated in the output, and it did move on to another robot and failed again.

    So the issue looks like inactive robots. But the script did handle those previously.

     

    The person that created the script is no longer around, and as you may be able to tell, I am now from a scripting background :\

     

    I can see in the scrip there is some handling of pkg_version returning nil. Could it be as simple as adding similar to the probe table?

     

    Example:

    if (hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] == nil) then
    hub_robot_probes[hub_entry.name][r_entry.name]["probes"][p_entry.name]["pkg_version"] = "-"
    end

     

    Thanks



  • 8.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)
    Best Answer

    Posted 03-28-2019 02:58 PM

    So right now you have the code:

     

    if ( r_entry.probelist == nil ) then -- catch questionable data situation

    tdump(r_entry) -- print enclosing table data

    print(nil .. nil) -- artificial error to stop code running

    end

     

    to catch the questionable data and abort.

     

    You can just turn the logic around to:

    if ( r_entry.probelist ~= nil ) then -- Only process robots with probelist defined

     

    Take out the tdump, print, and end.

     

    Then find the "end" that matches the "for" statement in the previous line of code and add another "end" statement just before it to match the "if".

     

    That way the code will ignore processing robots without the probelist defined.

     

    Not sure if you would want to note anything about the inactive robot but at least this will get past the failure.

     

    And it's unclear why this ever worked in the past though there is a defect in some of the hub versions where it will over time lose information about registered probes. Possible that this is in play here too. Otherwise I don't believe that this behavior has changed in a long time.



  • 9.  Re: lua script - bad argument #1 to 'pairs' (table expected, got nil)

    Posted 03-29-2019 05:52 AM

    Thanks again, Garin.

    This has got the script working again

    Much appreciated.