Adding New Custom Fields in Server Class in iTop CMDB tool

Adding New Custom Fields in Server Class in iTop CMDB tool

Adding New Custom Fields in Server Class in iTop CMDB Tool – Full DevOps Guide

If you manage infrastructure with iTop CMDB, you’ve likely hit the wall: the default Server class lacks critical fields like Patch History, Cluster Details, or How to Access. These gaps force teams to misuse Description or Notes fields, creating inconsistent data that breaks automation and reporting.

In this comprehensive DevOps tutorial, I’ll walk you through extending the iTop Server class with custom fields—exactly as I’ve done for production environments. You’ll learn:

  • How to structure an iTop extension module from scratch
  • XML datamodel syntax for field definitions (with real-world examples)
  • Database schema updates and toolkit validation
  • Troubleshooting common pitfalls (permission errors, delta conflicts)
  • Verification steps to confirm your fields work in the UI and API

By the end, you’ll have a deployable extension that adds four production-grade fields to your Server class, with zero downtime.

Prerequisites

Before touching code, ensure you have:

  • iTop 2.0+ installed on a non-production instance (I use a Docker container with combodo/itop:2.7 for testing).
  • SSH access to the server (or direct file access via SFTP/WinSCP).
  • A text editor that handles UTF-8 and Unix line endings:
    • Windows: Notepad++ or PSPad (avoid Notepad—it corrupts line endings).
    • Linux/macOS: nano, vim, or VS Code.
  • Basic familiarity with:
    • XML syntax (for datamodel.xml)
    • MySQL (to verify schema changes)
    • iTop’s object model (classes, attributes, deltas)

Critical Note: Always test extensions in a staging environment. I’ve seen teams brick production instances by skipping this step—recovery requires manual database surgery.

Step 1: Create an Empty Extension Module

iTop extensions are self-contained modules stored in the extensions/ directory. We’ll start with a skeleton module and build on it.

1.1 Generate the Module Structure

Use iTop’s module creation wizard (available in the toolkit) or manually create these files in a new folder under extensions/:

extensions/
└── server-custom-fields/
    ├── datamodel.server-custom-fields.xml
    ├── module.server-custom-fields.php
    ├── en.dict.server-custom-fields.php
    └── model.server-custom-fields.php

File Purposes:

  • datamodel.*.xml: Defines class modifications (our focus).
  • module.*.php: Module metadata (name, version, dependencies).
  • en.dict.*.php: Localization strings (labels, tooltips).
  • model.*.php: Optional PHP logic (e.g., computed fields).

1.2 Populate the Module Files

1. module.server-custom-fields.php:

<?php
//
// iTop module definition file
//
SetupWebPage::AddModule(
    __FILE__, // Path to the current file, all other file names are relative to the directory containing this file
    'server-custom-fields/1.0.0',
    array(
        // Module label
        'label' => 'Server Custom Fields',
        // Module description
        'description' => 'Adds custom fields to the Server class: Patch History, Cluster Details, How to Access, Additional Notes',
    ),
    array(
        // Dependencies (none for this simple extension)
    ),
    array(
        // Installation order (higher = installed later)
        'installer' => 'ServerCustomFieldsInstaller',
    )
);
?>

2. en.dict.server-custom-fields.php:

<?php
Dict::Add('EN US', 'English', 'English', array(
    'Class:Server/Attribute:patch_history' => 'Patch History',
    'Class:Server/Attribute:patch_history+' => 'List of applied patches and updates',
    'Class:Server/Attribute:cluster_details' => 'Cluster Details',
    'Class:Server/Attribute:cluster_details+' => 'Cluster membership and role (e.g., "Primary Node in HA Cluster")',
    'Class:Server/Attribute:how_to_access' => 'How to Access',
    'Class:Server/Attribute:how_to_access+' => 'Instructions for accessing the server (e.g., "SSH via bastion host: ssh user@bastion -L 2222:server:22")',
    'Class:Server/Attribute:additional_notes' => 'Additional Notes',
    'Class:Server/Attribute:additional_notes+' => 'Miscellaneous notes',
));
?>

3. datamodel.server-custom-fields.xml (empty for now):

<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
  <classes>
    <!-- Field definitions will go here -->
  </classes>
</itop_design>

1.3 Install the Empty Module

Follow these steps to register the module with iTop:

  1. Ensure the web server can write to conf/production/config-itop.php:
    • Linux: chmod 664 conf/production/config-itop.php
    • Windows: Right-click the file → Properties → Uncheck "Read-only".
  2. Navigate to http://your-itop/setup/ in your browser.
  3. Click "Continue »" to start the re-installation.
  4. Select "Update an existing instance" and click "Next »".
  5. On the "Extensions" screen, verify your module (server-custom-fields) appears in the list. If not:
    • Check the folder name matches the module ID (server-custom-fields).
    • Verify file permissions: chmod -R 755 extensions/server-custom-fields/ (Linux).
  6. Select your module and complete the installation.

Verification: After installation, check conf/production/config-itop.php for your module’s entry in the $MyModules array.

Step 2: Add Custom Fields to the Server Class

Now we’ll define the four fields in datamodel.server-custom-fields.xml. Each field requires:

  • A unique id (lowercase, underscores).
  • A xsi:type (e.g., AttributeText, AttributeString).
  • A _delta="define" attribute to indicate this is a new field.
  • Database column mapping via <sql>.

2.1 Define the Fields in XML

Replace the empty <classes> section in datamodel.server-custom-fields.xml with:

<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
  <classes>
    <class id="Server">
      <fields>
        <!-- Patch History: Multi-line text for tracking updates -->
        <field id="patch_history" xsi:type="AttributeText" _delta="define">
          <sql>patch_history</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
          <row_count>5</row_count> <!-- Renders as a 5-row textarea -->
        </field>

        <!-- Cluster Details: Single-line text for cluster info -->
        <field id="cluster_details" xsi:type="AttributeString" _delta="define">
          <sql>cluster_details</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
          <max_length>255</max_length>
        </field>

        <!-- How to Access: Multi-line text for access instructions -->
        <field id="how_to_access" xsi:type="AttributeText" _delta="define">
          <sql>how_to_access</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
          <row_count>3</row_count>
        </field>

        <!-- Additional Notes: Generic text field -->
        <field id="additional_notes" xsi:type="AttributeText" _delta="define">
          <sql>additional_notes</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
        </field>
      </fields>
    </class>
  </classes>
</itop_design>

Key Attributes Explained:

Attribute Purpose Example Values
xsi:type Field data type AttributeText (multi-line), AttributeString (single-line), AttributeDate, AttributeEnum
_delta Modification type "define" (new field), "redefine" (modify existing), "must_exist" (reference existing)
<sql> Database column name Must match id (or use a custom name, e.g., custom_patch_history)
<row_count> UI rendering (for AttributeText) Number of rows in the textarea

2.2 Validate the XML with the Toolkit

Before applying changes, validate the XML to catch syntax errors or conflicts:

  1. Navigate to http://your-itop/toolkit/.
  2. Click the "Check Data Model" tab.
  3. If errors appear:
    • Common Errors:
      • Unknown class 'Server': Typo in <class id="Server">.
      • Duplicate field 'notes': Field already exists (use _delta="redefine" if modifying).
      • Invalid xsi:type: Check spelling (e.g., AttributeText, not TextAttribute).
    • Fix errors in datamodel.server-custom-fields.xml and refresh the toolkit.

2.3 Apply the Changes

Once validation passes:

  1. In the toolkit, switch to the "Update iTop Code" tab.
  2. Click "Update iTop Code". This will:
    • Compile the XML datamodel into PHP classes.
    • Update the MySQL schema to add the new columns.
  3. Wait for the confirmation message: Code updated successfully.

Database Verification: Connect to MySQL and check the server table:

mysql -u root -p itop_db -e "DESCRIBE server;"

You should see the new columns (patch_history, cluster_details, etc.) with types matching your XML definitions (e.g., TEXT for AttributeText).

Step 3: Verify the Fields in iTop

After applying changes, confirm the fields appear in the UI and API:

3.1 Check the Server Class in the UI

  1. Log in to iTop as an admin.
  2. Navigate to Configuration Management → Servers.
  3. Open an existing server or create a new one.
  4. Verify the new fields appear under the "Details" tab, with labels from en.dict.server-custom-fields.php.

Troubleshooting Missing Fields:

  • Cache Issue: Clear the iTop cache:
    rm -rf /var/www/html/itop/data/cache-*
  • Permission Issue: Ensure the web server owns the extension files:
    chown -R www-data:www-data extensions/server-custom-fields/
  • Delta Conflict: If fields exist but aren’t editable, check for _delta="redefine" in your XML.

3.2 Test API Access

Use iTop’s REST/JSON API to confirm the fields are accessible:

curl -X POST "http://your-itop/webservices/rest.php?version=1.3" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "core/get",
    "class": "Server",
    "key": "SELECT Server WHERE name = \"web01\"",
    "output_fields": "name,patch_history,cluster_details"
  }'

Expected output (truncated):

{
  "objects": {
    "Server::1": {
      "name": "web01",
      "patch_history": "2023-10-01: Applied security patch KB12345",
      "cluster_details": "Primary node in HA cluster"
    }
  }
}

Common Pitfalls and Fixes

Pitfall Symptoms Solution
Module not listed in setup Extension doesn’t appear in the "Extensions" screen during setup.
  • Check folder name matches module ID (server-custom-fields).
  • Verify module.*.php has correct filename and SetupWebPage::AddModule call.
  • Check file permissions: chmod -R 755 extensions/.
Fields missing in UI Fields don’t appear in the Server class after installation.
  • Clear iTop cache: rm -rf data/cache-*.
  • Check datamodel.xml for typos in id or xsi:type.
  • Verify _delta="define" is present on all fields.
Database schema mismatch Toolkit reports "Column already exists" or "Unknown column".
  • Check for duplicate <sql> names in your XML.
  • If modifying an existing field, use _delta="redefine".
  • Manually drop the column in MySQL and re-run the toolkit:
    ALTER TABLE server DROP COLUMN patch_history;
Localization labels missing Fields show raw IDs (e.g., Class:Server/Attribute:patch_history) instead of labels.
  • Verify en.dict.*.php has entries for all fields.
  • Check for typos in the dictionary keys (e.g., Class:Server/Attribute:patch_history).
  • Clear the cache after fixing dictionary files.

Deploying to Production

Once tested in staging, deploy the extension to production:

  1. Backup the database:
    mysqldump -u root -p itop_db > itop_prod_backup.sql
  2. Copy the extension:
    scp -r extensions/server-custom-fields/ user@prod-server:/var/www/html/itop/extensions/
  3. Run the setup:
    1. Navigate to http://prod-itop/setup/.
    2. Select "Update an existing instance".
    3. Enable your module and complete the installation.
  4. Verify:
    • Check the Server class in the UI.
    • Run a test API query (see Step 3.2).

Key Takeaways

  • Extensions are self-contained: All changes live in a single folder under extensions/, making them portable and version-controlled.
  • XML datamodel is declarative: Define fields with <field> tags, and iTop handles the rest (database schema, UI rendering, API exposure).
  • Delta attributes control behavior:
    • _delta="define": Add a new field.
    • _delta="redefine": Modify an existing field.
    • _delta="must_exist": Reference an existing field (e.g., for computed fields).
  • Toolkit is your safety net: Always validate XML before applying changes to avoid schema corruption.
  • Localization matters: Use dictionary files (en.dict.*.php) for user-friendly labels and tooltips.

FAQ

How do I add a dropdown (enum) field to the Server class?

Use xsi:type="AttributeEnum" in your XML and define the values in <values>:

<field id="environment" xsi:type="AttributeEnum" _delta="define">
  <sql>environment</sql>
  <values>
    <value id="prod">Production</value>
    <value id="staging">Staging</value>
    <value id="dev">Development</value>
  </values>
  <default_value>dev</default_value>
</field>

Add localization in en.dict.*.php:

Dict::Add('EN US', 'English', 'English', array(
    'Class:Server/Attribute:environment' => 'Environment',
    'Class:Server/Attribute:environment/Value:prod' => 'Production',
    'Class:Server/Attribute:environment/Value:staging' => 'Staging',
    'Class:Server/Attribute:environment/Value:dev' => 'Development',
));

Can I add a field to a class that’s part of a core module (e.g., PhysicalDevice)?

Yes, but you must declare the dependency in module.*.php:

SetupWebPage::AddModule(
    __FILE__,
    'server-custom-fields/1.0.0',
    array(
        'label' => 'Server Custom Fields',
        'description' => '...',
    ),
    array(
        'itop-config-mgmt/2.0.0', // Dependency on the core module
    ),
    array(
        'installer' => 'ServerCustomFieldsInstaller',
    )
);

Then reference the class in your XML as usual:

<class id="PhysicalDevice">
  <fields>
    <field id="asset_tag" xsi:type="AttributeString" _delta="define">
      <sql>asset_tag</sql>
    </field>
  </fields>
</class>

How do I make a field mandatory?

Set <is_null_allowed>false</is_null_allowed> in the XML and provide a <default_value> if needed:

<field id="environment" xsi:type="AttributeEnum" _delta="define">
  <sql>environment</sql>
  <is_null_allowed>false</is_null_allowed>
  <default_value>dev</default_value>
  <values>...</values>
</field>

Note: Mandatory fields may break existing objects if they lack a value. Use the toolkit’s "Data Integrity" tab to check for violations.

How do I remove a custom field later?

To remove a field:

🛒 Recommended gear on Amazon

Disclosure: some links above are affiliate links — if you buy through them I may earn a small commission at no extra cost to you. Thanks for supporting the channel!

4 Comments

  1. Hi thanks for the tutorial. I am trying to achieve something with the user request. If you see the user request there is no option to choose the custom start date. It takes the date and time of ticket creation. Could you guide me how to add a date control to choose a custom date instead of default one? Thanks in advance. -

    ReplyDelete
  2. Hi, yeah this piece of writing is truly good and I have learned lot of things from it concerning blogging. thanks.

    ReplyDelete
  3. I used to be recommended this blog by way of my cousin. I'm now not sure whether this submit is written via him as no one else recognize such particular approximately my problem. You are incredible! Thank you!

    ReplyDelete
  4. hi i have try it but im getting
    Error: Error loading module "sample-extension": /itop_design/classes/class[Server] at line 4: could not be found - Loaded modules: dictionaries,core,application,authent-cas,authent-external,authent-ldap,authent-local,combodo-db-tools,itop-attachments,itop-backup,itop-config,itop-files-information,itop-portal-base,itop-portal,itop-profiles-itil,itop-sla-computation,itop-structure,itop-tickets,itop-welcome-itil,sample-extension
    this error.
    can anyone help me with it

    ReplyDelete
Previous Post Next Post