[racktables-users] Re: Help with Object Import

  • From: Ernest Shaffer <ernest.shaffer@xxxxxxxxx>
  • To: racktables-users@xxxxxxxxxxxxx
  • Date: Wed, 1 Apr 2009 10:35:18 -0700

Thank you both for the good feedback.

I'm hoping to get a csv_import.php script together and maybe I can post it if its not to big, or messy.

Thanks again,
Ernie


On Apr 1, 2009, at 10:05 AM, Gabriel Friedmann wrote:

Hi, Ernest.

I learned a couple things when I was exploring asset importing.  I was
pulling data out of OpenNMS and into RackTables.  This included
hostnames, attributes, multiple interfaces, multiple IP addresses, and
category information.  I only put it together for a quick
proof-of-concept and it is nowhere near robust enough for actual use,
but I did have my eye on regularly updating RackTables info from another
authority.

These are some lessons I learned that may provide a head start.  The
Export/Import definitely takes some design planning.  The main aspects
are 1) You need a unique asset identifier.  2) Use separate logic for
attributes and Tags. 3) Make some great logging for success or fail
conditions.


Straight CSV might not work very well if you want to import multiple IP addresses, multiple tags and text-comment fields. In my case the comment
field had quotes for URLs, so quoting the fields didn't help.  I ended
up using a using | to delineate fields.  Also, I made two different
files to import.


File 1: asset number|hostname|description|location|comment
field|IP|interfaceid|interface name|HW address
[Lines could be repeated, and if the asset already existed, then import
just updated with the additional comment/interface/IP information]


File 2: asset number|tag1|tag2|tag3....


For importing data, I found it helpful to create a php include file to
source from my import scripts.  This acts as a wrapper for the more
abstract import/update racktables functions but does not rely on web
interface functions or data. I figure this may be more robust than going
for a direct database import. [See the code pasted at the end of this
email]

Watch out for functions that are finicky and want NULL or an empty
string '' arguments.
Interesting functions
 //commitAddObject ($new_name, $new_label, $new_barcode, $new_type_id,
$new_asset_no, $taglist = array())      

//commitUpdateObject ($object_id = 0, $new_name = '', $new_label = '',
$new_barcode = '', $new_type_id = 0, $new_has_problems = 'no',
$new_asset_no = '', $new_comment = '')
 // $object_id and $new_type_id is required
//this updates with the values of ALL provided, even if empty or NULL!


 //commitUpdateAttrValue ($object_id = 0, $attr_id = 0, $value = '')

 //commitAddPort ($object_id = 0, $port_name, $port_type_id,
$port_label, $port_l2address)

 //bindIpToObject ($details['ip'] , $object_id, $details['ifname'],
'regular');


Also, when using the useSelectBlade($query) function for SQL queries, I
had to do a silly dance before it would allow another query.

 $result = useSelectBlade ($query, __FUNCTION__);
 $row = $result->fetch (PDO::FETCH_ASSOC);
 //do bugfix.  Sometimes we can't re-query unless we have fetched all
results, even blank ones
 do $result->fetchAll();
 while ($result->nextRowSet());
 $result->closeCursor();
 unset($result);


That should save some hours of head smashing for others who may take on
this task.

Good Luck,
Gabriel Friedmann

---------------myCLIinit.php---------------------
<?php

//require 'inc/init.php';
//fixContext();

require_once 'inc/config.php';
require_once 'inc/functions.php';
require_once 'inc/database.php';
require_once 'inc/secret.php';

// Now try to connect...
try
{
       $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password);
}
catch (PDOException $e)
{
showError ("Database connection failed:\n\n" . $e- >getMessage(),
__FILE__);
       exit (1);
}

$dbxlink->exec ("set names 'utf8'");

$dbver = getDatabaseVersion();
if ($dbver != CODE_VERSION)
{
       echo '<p align=justify>This Racktables installation seems to be
' .
               'just upgraded to version ' . CODE_VERSION . ', while
the '.
               'database version is ' . $dbver . '. This THING WONT
WORK! ';
       exit (1);
}

if (!mb_internal_encoding ('UTF-8') or !mb_regex_encoding ('UTF-8'))
{
       showError ('Failed setting multibyte string encoding to UTF-8',
__FILE__);
       exit (1);
}

//Need to define own function showError() that is usually defined in
interface.php
//  It is called when there is a DB query problem.

function showError ($info = '', $location = 'N/A')
{
       echo "An error has occured in [${location}]. ";
       if (empty ($info))
               echo 'No additional information is available.';
       else
               echo "Additional information: ${info}\n";
}


$configCache = loadConfigCache();
if (!count ($configCache))
{
       print "Failed to load configuration from the database. " .
__FILE__ . "\n";
       exit (1);
}


?>



-----Original Message-----
From: racktables-users-bounce@xxxxxxxxxxxxx
[mailto:racktables-users-bounce@xxxxxxxxxxxxx] On Behalf Of Denis
Ovsienko
Sent: Wednesday, April 01, 2009 2:54 AM
To: racktables-users@xxxxxxxxxxxxx
Subject: [racktables-users] Re: Help with Object Import


I am going to migrate 400+ hosts from a home grown inventory database
into
RackTables.

I figured why not ask for advice to make sure I am not re-inventing
the
wheel.  Does anyone have an example script, or is there a way to use
the
existing RackTables code to import from a flat file? I can export the
data
into a flat file with the needed fields. Then I'd like to import as
much
information as possible, meaning static data, optional attributes and
tags,
if at all possible.

Ernest, you seem to be the first one.

There are two relatively idependent works here: to export from one
database and to import to another. First you need to stick with the
format of intermediate file, IOW, with the set and ordering of CSV file
columns. After that you make a backup of your RackTables database and
start debugging your import script, which is a bit more, than the
example code from php.net:


$handle = fopen("test.csv", "r");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $cname = $data[0];
        $asset_tag = $data[1];
        commitAddObject ($cname, '', '', 4, $asset_tag);
}

To add data about optional attributes in the same cycle, you need to map
the string retrieved from CSV into key value from the dictionary with
own function. Then, if the mapping was successful, the following pattern
would store the value:

// get the object_id of the last object added
// $object_id = ...

if (($key = os_to_key ($osname)) != NULL)
        // set "SW type"
        commitUpdateAttrValue ($object_id, 4, $key);

if (($key = hardware_to_key ($hwname) != NULL)
        // set "HW type"
        commitUpdateAttrValue ($object_id, 2, $key);

... and so on. You'll definitely have to restore from backup and re- run
the import script several times until the actual result is what you
intended.

--




Other related posts: