cPanel Blog

December 2009

Known Integration Issues inside of 11.25

| No TrackBacks

As most of you probably know, we released 11.25 to our RELEASE branch this week.  This is a major change to cPanel/WHM which presents some issues with integration.  I have been trying to track as many integration support requests as possible so that I can get an idea of what common issues have arisen.  Here is a summary of the issues and what we are doing about them.

Hooks Do Not Execute
We have added a feature to 11.25.0 that keeps track of what hooks are in use.  This new mechanism greatly improves speed within cPanel/WHM as it no longer has to check to see if a hook exists every time an API call is made.  Unfortunately the hooks.db file was unreadable by any user other than root.  If you notice that hooks are not executing on your server, please run chmod 644 /var/cpanel/hooks.db.  This issue will be fixed in the next update.

The setresellerlimits XML API call does not work with certain reseller accounts.
The setresellerlimits XML API call does not work with reseller accounts that did not previously have reseller limits.  This is because the hash in /var/cpanel/reseller-limits.yaml is not being properly created.  This issue will be resolved in the next update.

API call changes that affect hook/CustomEventHandlers
We are moving toward making most of cPanel use API2 calls for executing events.  This provides a much more flexible system.  However, a major drawback to doing so is that some hooks will break.  For example, we changed Email::addpop to an API2 call in the interface.  When the addpop hook is executed, it is passed a hash rather than an array, making the hook unusable.  We have updated the following interfaces to use API2:

  • Email Accounts
  • Cron
  • Change MX Record

Please be aware of this change if you use hooks.  If you need assistance, please post in the developer discussions forum and we will try to assist you as best we can.

XML-API Authentication
The XML-API no longer prompts for HTTP authentication.  Most of the time this is not an issue.  In some cases we have encountered HTTP libraries (wget) that wait for HTTP authentication requests before sending headers.  You will now need to send headers with the initial request.

You can track new releases at httpupdate.cpanel.net and compare your build number and the time of the build vs. what you have in /usr/local/capnel/version.

How to trace the cPanel API

| No TrackBacks

At this point, cPanel’s APIs are not 100% documented.  We are working on it and hope to have complete API docs up in a few months.  I’ve written a CustomEventHandler that will print every API call made into cpanel’s error_log (/usr/local/cpanel/logs/error_log).  

Installation
 
To use the API Tracer, you will need to download it, then place the Dumper.pm file at /usr/local/cpanel/perl/Dumper and the CustomEventHandler.pm file at /usr/local/cpanel/Cpanel.
 
Once this has been put into the proper location, cPanel will automatically start logging API calls to the error_log.  To view each call, you simply need to run tail -f /usr/local/cpanel/logs/error_log and login to a cPanel interface to start seeing data.
 
Filtering
 
90% of the information displayed by the API Tracer is probably not what you are looking for.  If you look at the code for this CustomEventHandler, you will see that the following pieces of information are passed to it:
 
my ( $apiv, $type, $module, $event, $cfgref, $dataref ) = @_;
 
Out of these, for the purpose of filtering, the only ones that we care about are the following variables:
 
$apiv - API Version
$module - The module of the function being called
$event - The name of the function being called
 
When a custom event handler runs, it is executed both before and after the call has been completed.  This is indicated by the $type variable which will pass “pre” before the event has been executed and “post” after the event has been executed.  The most important thing to note here is that in the event of a “pre” call, if CustomEventHandler returns a false value, it will stop execution of the event, so in this scenario it is very important to always return 1.  For example, if you are trying to filter an email event, you will see something like the following right after the first line of the event() function:
 
return 1 if $module ne ‘email’;
 
It is also important to note that modules and function names are passed in lowercase form to the CustomEventHandler.
 
If you want to filter for a very specific call, you would do something like the following
 
return 1 if module ne ‘email’ && $event ne ‘addpop’;
 
Understanding the Data passed to the tracer
 
Now that you understand how the tracer operates and how to make it report useful information, we need to talk about how to understand the data that it gives.
 
As you will see, the Tracer will print formatted text to the error log that looks something like this:

--------------------
mysql:adduserdb
$apiv = 1
$type = pre
-----
$cfgref

$VAR1 = {
          'param0' => 'cptest_dbname',
          'param1' => 'cptest_username',
          'param2' => 'ALTER CREATEROUTINE TEMPORARY CREATE DELETE DROP SELECT INSERT UPDATE REFERENCES INDEX LOCK '
        };

mysql:adduserdb 
--------------------
mysql:adduserdb
$apiv = 1
$type = post
-----
$cfgref

$VAR1 = {
          'param0' => 'cptest_dbname',
          'param1' => 'cptest_username',
          'param2' => 'ALTER CREATEROUTINE TEMPORARY CREATE DELETE DROP SELECT INSERT UPDATE REFERENCES INDEX LOCK '
        };

-----
output
 
 
The first line indicates the module and the version, the second line describes which API version it’s using (either API1 (link) or API2 (link) ).  After this, it displays two variables, $cfgref and $dataref.  These two variables indicate the input ($cfgref) and output ($dataref) from the function in a Data::Dumper format.
 
Understanding $cfgref
 
As API1 and API2 use different methods of input, they naturally have different methods of displaying within this module.  When using API1 you will see something like the following:
 
$VAR1 = {
          'param0' => 'cptest_dbname',
          'param1' => 'cptest_',
          'param2' => 'ALTER CREATEROUTINE TEMPORARY CREATE DELETE DROP SELECT INSERT UPDATE REFERENCES INDEX LOCK '
        };
 
 
These indicate the order of parameters to API1, starting with param0 to paramn.  This data can be correlated to what input was given to the cPanel interface to determine the call.
 
With API2, since it uses named parameters, rather than ordered parameters you will see something like the following:

$cfgref

$VAR1 = {
          'quota' => 250,
          'password' => 'somepasswprd',
          'domain' => 'somedomain.com',
          'email' => 'someuser'
        };
 
 
 
With these, the parameter name maps directly to the parameter name for API2.  This is fairly easy to understand, however there are a few things that need to be noted.  Firstly, use of generic parameters that will probably not aid you.  There are a few of these mostly prefixed with “api2_”, are used for things like sorting, pagination, searching, etc.  The other main parameter to pay attention to is “cache_fix” which is used for browser caching and should always be ignored.
 
Understanding the output from $dataref
 
One thing that you will only see in “post” calls, is the $dataref being populated.  This contains the output from the Tracer. API1 output is usually straight forward, as they return strings rather than data structures. Take for example, Email::addpop, it will return the name of the email address:
 
email+domain.com
 
This will be populated with an error message in the case of an error.
 
API2, as it’s far more robust than API1, returns actual data structures.  These can be complex to work with.  Please refer to the API2 documentation (link) on how to work with this data.  When it is returned it will look like the following:
 
          {
            'diskquota' => 250,
            'humandiskquota' => '250 MB',
            'user' => 'asdge33',
            '_diskused' => 0,
            'humandiskused' => 'None',
            '_diskquota' => 262144000,
            'txtdiskquota' => 250,
            'diskusedpercent' => 0,
            'diskusedpercent20' => 0,
            'login' => 'asdge33@cptest.com',
            'domain' => 'cptest.com',
            'diskused' => 0,
            'email' => 'asdge33@cptest.com'
          },
 
This would be displayed in XML format via the XML-API by:
 
<data>
<_diskquota>262144000</_diskquota>
<_diskused>0</_diskused>
<diskquota>250</diskquota>
<diskused>0</diskused>
<diskusedpercent>0</diskusedpercent>
<diskusedpercent20>0</diskusedpercent20>
<domain>cptest.com</domain>
<email>asdge33@cptest.com</email>
<humandiskquota>250 MB</humandiskquota>
<humandiskused>None</humandiskused>
<login>asdge33@cptest.com</login>
<txtdiskquota>250</txtdiskquota>
<user>asdge33</user>
</data>
 
 
There are some shortcomings that need to be noted:
 
1.) This version of Tracer requires that /dev/shm to be writable, the path for the temp file can be edited within the script however /dev/shm is the fastest place.
2.) This means that usernames and passwords for anything created/modified through the cPanel interface will be written to the error_log.  You need to clear the error_log after enabling this, and be careful that it’s not left running on a production server due to the inherent security risks.