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.7for testing). - SSH access to the server (or direct file access via SFTP/WinSCP).
- A text editor that handles UTF-8 and Unix line endings:
- Basic familiarity with:
- XML syntax (for
datamodel.xml) - MySQL (to verify schema changes)
- iTop’s object model (classes, attributes, deltas)
- XML syntax (for
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:
- 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".
- Linux:
- Navigate to
http://your-itop/setup/in your browser. - Click "Continue »" to start the re-installation.
- Select "Update an existing instance" and click "Next »".
- 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).
- Check the folder name matches the module ID (
- 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:
- Navigate to
http://your-itop/toolkit/. - Click the "Check Data Model" tab.
- 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, notTextAttribute).
- Fix errors in
datamodel.server-custom-fields.xmland refresh the toolkit.
- Common Errors:
2.3 Apply the Changes
Once validation passes:
- In the toolkit, switch to the "Update iTop Code" tab.
- Click "Update iTop Code". This will:
- Compile the XML datamodel into PHP classes.
- Update the MySQL schema to add the new columns.
- 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
- Log in to iTop as an admin.
- Navigate to Configuration Management → Servers.
- Open an existing server or create a new one.
- 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. |
|
| Fields missing in UI | Fields don’t appear in the Server class after installation. |
|
| Database schema mismatch | Toolkit reports "Column already exists" or "Unknown column". |
|
| Localization labels missing | Fields show raw IDs (e.g., Class:Server/Attribute:patch_history) instead of labels. |
|
Deploying to Production
Once tested in staging, deploy the extension to production:
- Backup the database:
mysqldump -u root -p itop_db > itop_prod_backup.sql - Copy the extension:
scp -r extensions/server-custom-fields/ user@prod-server:/var/www/html/itop/extensions/ - Run the setup:
- Navigate to
http://prod-itop/setup/. - Select "Update an existing instance".
- Enable your module and complete the installation.
- Navigate to
- 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 AmazonDisclosure: 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!
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. -
ReplyDeleteHi, yeah this piece of writing is truly good and I have learned lot of things from it concerning blogging. thanks.
ReplyDeleteI 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!
ReplyDeletehi i have try it but im getting
ReplyDeleteError: 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